Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: third_party/polymer/v1_0/components-chromium/app-layout/app-header/app-header-extracted.js

Issue 1984963002: Roll Polymer elements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 Polymer({
2 is: 'app-header',
3
4 behaviors: [
5 Polymer.AppScrollEffectsBehavior,
6 Polymer.IronResizableBehavior
7 ],
8
9 properties: {
10 /**
11 * If true, the header will automatically collapse when scrolling down.
12 * That is, the `primary` element remains visible when the header is ful ly condensed
13 * whereas the rest of the elements will collapse below `primary` elemen t.
14 *
15 * By default, the `primary` element is the first toolbar in the light D OM:
16 *
17 *```html
18 * <app-header condenses>
19 * <app-toolbar>This toolbar remains on top</app-toolbar>
20 * <app-toolbar></app-toolbar>
21 * <app-toolbar></app-toolbar>
22 * </app-header>
23 * ```
24 *
25 * Additionally, you can specify which toolbar or element remains visibl e in condensed mode
26 * by adding the `primary` attribute to that element. For example: if we want the last
27 * toolbar to remain visible, we can add the `primary` attribute to it.
28 *
29 *```html
30 * <app-header condenses>
31 * <app-toolbar></app-toolbar>
32 * <app-toolbar></app-toolbar>
33 * <app-toolbar primary>This toolbar remains on top</app-toolbar>
34 * </app-header>
35 * ```
36 *
37 * Note the `primary` element must be a child of `app-header`.
38 */
39 condenses: {
40 type: Boolean,
41 value: false
42 },
43
44 /**
45 * Mantains the header fixed at the top so it never moves away.
46 */
47 fixed: {
48 type: Boolean,
49 value: false
50 },
51
52 /**
53 * Slides back the header when scrolling back up.
54 */
55 reveals: {
56 type: Boolean,
57 value: false
58 },
59
60 /**
61 * Displays a shadow below the header.
62 */
63 shadow: {
64 type: Boolean,
65 reflectToAttribute: true,
66 value: false
67 }
68 },
69
70 observers: [
71 'resetLayout(isAttached, condenses, fixed)'
72 ],
73
74 listeners: {
75 'iron-resize': '_resizeHandler'
76 },
77
78 /**
79 * A cached offsetHeight of the current element.
80 *
81 * @type {number}
82 */
83 _height: 0,
84
85 /**
86 * The distance in pixels the header will be translated to when scrolling.
87 *
88 * @type {number}
89 */
90 _dHeight: 0,
91
92 /**
93 * The offsetTop of `_primaryEl`
94 *
95 * @type {number}
96 */
97 _primaryElTop: 0,
98
99 /**
100 * The element that remains visible when the header condenses.
101 *
102 * @type {HTMLElement}
103 */
104 _primaryEl: null,
105
106 /**
107 * The header's top value used for the `transformY`
108 *
109 * @type {number}
110 */
111 _top: 0,
112
113 /**
114 * The current scroll progress.
115 *
116 * @type {number}
117 */
118 _progress: 0,
119
120 _wasScrollingDown: false,
121 _initScrollTop: 0,
122 _initTimestamp: 0,
123 _lastTimestamp: 0,
124 _lastScrollTop: 0,
125
126 /**
127 * The distance the header is allowed to move away.
128 *
129 * @type {number}
130 */
131 get _maxHeaderTop() {
132 return this.fixed ? this._dHeight : this._height + 5;
133 },
134
135 /**
136 * Returns a reference to the element that remains visible when the header condenses.
137 *
138 * @return {HTMLElement}?
139 */
140 _getPrimaryEl: function() {
141 /** @type {HTMLElement} */
142 var primaryEl;
143 var nodes = Polymer.dom(this.$.content).getDistributedNodes();
144
145 for (var i = 0; i < nodes.length; i++) {
146 if (nodes[i].nodeType === Node.ELEMENT_NODE) {
147 var node = /** @type {HTMLElement} */ (nodes[i]);
148 if (node.hasAttribute('primary')) {
149 primaryEl = node;
150 break;
151 } else if (!primaryEl) {
152 primaryEl = node;
153 }
154 }
155 }
156 return primaryEl;
157 },
158
159 /**
160 * Resets the layout. If you changed the size of app-header via CSS
161 * you can notify the changes by either firing the `iron-resize` event
162 * or calling `resetLayout` directly.
163 *
164 * @method resetLayout
165 */
166 resetLayout: function() {
167 this.fire('app-header-reset-layout');
168
169 this.debounce('_resetLayout', function() {
170 // noop if the header isn't visible
171 if (this.offsetWidth === 0 && this.offsetHeight === 0) {
172 return;
173 }
174
175 var scrollTop = this._clampedScrollTop;
176 var firstSetup = this._height === 0 || scrollTop === 0;
177 var currentDisabled = this.disabled;
178
179 this._height = this.offsetHeight;
180 this._primaryEl = this._getPrimaryEl();
181 this.disabled = true;
182
183 // prepare for measurement
184 if (!firstSetup) {
185 this._updateScrollState(0, true);
186 }
187
188 if (this._mayMove()) {
189 this._dHeight = this._primaryEl ? this._height - this._primaryEl.off setHeight : 0;
190 } else {
191 this._dHeight = 0;
192 }
193
194 this._primaryElTop = this._primaryEl ? this._primaryEl.offsetTop : 0;
195 this._setUpEffect();
196
197 if (firstSetup) {
198 this._updateScrollState(scrollTop, true);
199 } else {
200 this._updateScrollState(this._lastScrollTop, true);
201 this._layoutIfDirty();
202 }
203 // restore no transition
204 this.disabled = currentDisabled;
205 });
206 },
207
208 /**
209 * Updates the scroll state.
210 *
211 * @param {number} scrollTop
212 * @param {boolean=} forceUpdate (default: false)
213 */
214 _updateScrollState: function(scrollTop, forceUpdate) {
215 if (this._height === 0) {
216 return;
217 }
218
219 var progress = 0;
220 var top = 0;
221 var lastTop = this._top;
222 var lastScrollTop = this._lastScrollTop;
223 var maxHeaderTop = this._maxHeaderTop;
224 var dScrollTop = scrollTop - this._lastScrollTop;
225 var absDScrollTop = Math.abs(dScrollTop);
226 var isScrollingDown = scrollTop > this._lastScrollTop;
227 var now = Date.now();
228
229 if (this._mayMove()) {
230 top = this._clamp(this.reveals ? lastTop + dScrollTop : scrollTop, 0, maxHeaderTop);
231 }
232
233 if (scrollTop >= this._dHeight) {
234 top = this.condenses ? Math.max(this._dHeight, top) : top;
235 this.style.transitionDuration = '0ms';
236 }
237
238 if (this.reveals && !this.disabled && absDScrollTop < 100) {
239 // set the initial scroll position
240 if (now - this._initTimestamp > 300 || this._wasScrollingDown !== isSc rollingDown) {
241 this._initScrollTop = scrollTop;
242 this._initTimestamp = now;
243 }
244
245 if (scrollTop >= maxHeaderTop) {
246 // check if the header is allowed to snap
247 if (Math.abs(this._initScrollTop - scrollTop) > 30 || absDScrollTop > 10) {
248 if (isScrollingDown && scrollTop >= maxHeaderTop) {
249 top = maxHeaderTop;
250 } else if (!isScrollingDown && scrollTop >= this._dHeight) {
251 top = this.condenses ? this._dHeight : 0;
252 }
253
254 var scrollVelocity = dScrollTop / (now - this._lastTimestamp);
255 this.style.transitionDuration = this._clamp((top - lastTop) / scro llVelocity, 0, 300) + 'ms';
256 } else {
257 top = this._top;
258 }
259 }
260 }
261
262 if (this._dHeight === 0) {
263 progress = scrollTop > 0 ? 1 : 0;
264 } else {
265 progress = top / this._dHeight;
266 }
267
268 if (!forceUpdate) {
269 this._lastScrollTop = scrollTop;
270 this._top = top;
271 this._wasScrollingDown = isScrollingDown;
272 this._lastTimestamp = now;
273 }
274
275 if (forceUpdate || progress !== this._progress || lastTop !== top || scr ollTop === 0) {
276 this._progress = progress;
277 this._runEffects(progress, top);
278 this._transformHeader(top);
279 }
280 },
281
282 /**
283 * Returns true if the current header is allowed to move as the user scrol ls.
284 *
285 * @return {boolean}
286 */
287 _mayMove: function() {
288 return this.condenses || !this.fixed;
289 },
290
291 /**
292 * Returns true if the current header will condense based on the size of t he header
293 * and the `consenses` property.
294 *
295 * @return {boolean}
296 */
297 willCondense: function() {
298 return this._dHeight > 0 && this.condenses;
299 },
300
301 /**
302 * Returns true if the current element is on the screen.
303 * That is, visible in the current viewport.
304 *
305 * @method isOnScreen
306 * @return {boolean}
307 */
308 isOnScreen: function() {
309 return this._height !== 0 && this._top < this._height;
310 },
311
312 /**
313 * Returns true if there's content below the current element.
314 *
315 * @method isContentBelow
316 * @return {boolean}
317 */
318 isContentBelow: function() {
319 if (this._top === 0) {
320 return this._clampedScrollTop > 0;
321 }
322
323 return this._clampedScrollTop - this._maxHeaderTop >= 0;
324 },
325
326 /**
327 * Transforms the header.
328 *
329 * @param {number} y
330 */
331 _transformHeader: function(y) {
332 this.translate3d(0, (-y) + 'px', 0);
333
334 if (this._primaryEl && this.condenses && y >= this._primaryElTop) {
335 this.translate3d(0, (Math.min(y, this._dHeight) - this._primaryElTop) + 'px', 0,
336 this._primaryEl);
337 }
338 },
339
340 _resizeHandler: function() {
341 this.resetLayout();
342 },
343
344 _clamp: function(v, min, max) {
345 return Math.min(max, Math.max(min, v));
346 },
347
348 /**
349 * Returns an object containing the progress value of the scroll effects
350 * and the top position of the header.
351 *
352 * @method getScrollState
353 * @return {Object}
354 */
355 getScrollState: function() {
356 return { progress: this._progress, top: this._top };
357 }
358
359 /**
360 * Fires when the layout of `app-header` changed.
361 *
362 * @event app-header-reset-layout
363 */
364 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698