OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Calls |readyTest| repeatedly until it returns true, then calls | |
7 * |readyCallback|. | |
8 * @param {function():boolean} readyTest | |
9 * @param {!Function} readyCallback | |
10 */ | |
11 function doWhenReady(readyTest, readyCallback) { | |
12 // TODO(dschuyler): Determine whether this hack can be removed. | |
13 // See also: https://github.com/Polymer/polymer/issues/3629 | |
14 var intervalId = setInterval(function() { | |
15 if (readyTest()) { | |
16 clearInterval(intervalId); | |
17 readyCallback(); | |
18 } | |
19 }, 10); | |
20 } | |
21 | |
22 /** | |
23 * Responds to route changes by expanding, collapsing, or scrolling to sections | 6 * Responds to route changes by expanding, collapsing, or scrolling to sections |
24 * on the page. Expanded sections take up the full height of the container. At | 7 * on the page. Expanded sections take up the full height of the container. At |
25 * most one section should be expanded at any given time. | 8 * most one section should be expanded at any given time. |
26 * @polymerBehavior MainPageBehavior | 9 * @polymerBehavior MainPageBehavior |
27 */ | 10 */ |
28 var MainPageBehaviorImpl = { | 11 var MainPageBehaviorImpl = { |
29 /** @type {?HTMLElement} The scrolling container. */ | 12 /** @type {?HTMLElement} The scrolling container. */ |
30 scroller: null, | 13 scroller: null, |
31 | 14 |
32 /** @override */ | 15 /** @override */ |
33 attached: function() { | 16 attached: function() { |
34 if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL') | 17 if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL') |
35 this.scroller = this.domHost.parentNode.scroller; | 18 this.scroller = this.domHost.parentNode.scroller; |
36 else | 19 else |
37 this.scroller = document.body; // Used in unit tests. | 20 this.scroller = document.body; // Used in unit tests. |
38 }, | 21 }, |
39 | 22 |
40 /** | 23 /** |
41 * @param {!settings.Route} newRoute | 24 * @param {!settings.Route} newRoute |
42 * @param {settings.Route} oldRoute | 25 * @param {settings.Route} oldRoute |
43 */ | 26 */ |
44 currentRouteChanged: function(newRoute, oldRoute) { | 27 currentRouteChanged: function(newRoute, oldRoute) { |
45 if (oldRoute || !newRoute.section) { | 28 // Allow the page to load before expanding the section. |
| 29 if (!oldRoute) |
| 30 setTimeout(this.tryTransitionToSection_.bind(this)); |
| 31 else |
46 this.tryTransitionToSection_(); | 32 this.tryTransitionToSection_(); |
47 return; | |
48 } | |
49 | |
50 // Wait for the page to really be ready before expanding or scrolling to the | |
51 // section. TODO(michaelpg): Remove this workaround with a global workaround | |
52 // for crbug.com/638074. | |
53 doWhenReady(function() { | |
54 if (newRoute != settings.getCurrentRoute()) | |
55 return; | |
56 var section = this.getSection(newRoute.section); | |
57 return section && (!newRoute.isSubpage() || section.canAnimateExpand()); | |
58 }.bind(this), this.tryTransitionToSection_.bind(this)); | |
59 }, | 33 }, |
60 | 34 |
61 /** | 35 /** |
62 * If possible, transitions to the current route's section (by expanding or | 36 * If possible, transitions to the current route's section (by expanding or |
63 * scrolling to it). If another transition is running, finishes or cancels | 37 * scrolling to it). If another transition is running, finishes or cancels |
64 * that one, then schedules this function again. This ensures the current | 38 * that one, then schedules this function again. This ensures the current |
65 * section is quickly shown, without getting the page into a broken state -- | 39 * section is quickly shown, without getting the page into a broken state -- |
66 * if currentRoute changes in between calls, just transition to the new route. | 40 * if currentRoute changes in between calls, just transition to the new route. |
67 * @private | 41 * @private |
68 */ | 42 */ |
(...skipping 15 matching lines...) Expand all Loading... |
84 if (expandedSection) { | 58 if (expandedSection) { |
85 // If the section shouldn't be expanded, collapse it. | 59 // If the section shouldn't be expanded, collapse it. |
86 if (!currentRoute.isSubpage() || expandedSection != currentSection) { | 60 if (!currentRoute.isSubpage() || expandedSection != currentSection) { |
87 promise = this.collapseSection_(expandedSection); | 61 promise = this.collapseSection_(expandedSection); |
88 // Scroll to the collapsed section. | 62 // Scroll to the collapsed section. |
89 if (currentSection) | 63 if (currentSection) |
90 this.scrollToSection_(); | 64 this.scrollToSection_(); |
91 } | 65 } |
92 } else if (currentSection) { | 66 } else if (currentSection) { |
93 // Expand the section into a subpage or scroll to it on the main page. | 67 // Expand the section into a subpage or scroll to it on the main page. |
| 68 if (!currentSection.clientHeight) { |
| 69 setTimeout(this.tryTransitionToSection_.bind(this)); |
| 70 return; |
| 71 } |
94 if (currentRoute.isSubpage()) | 72 if (currentRoute.isSubpage()) |
95 promise = this.expandSection_(currentSection); | 73 promise = this.expandSection_(currentSection); |
96 else | 74 else |
97 this.scrollToSection_(); | 75 this.scrollToSection_(); |
98 } | 76 } |
99 | 77 |
100 // When this animation ends, another may be necessary. Call this function | 78 // When this animation ends, another may be necessary. Call this function |
101 // again after the promise resolves. | 79 // again after the promise resolves. |
102 if (promise) | 80 if (promise) |
103 promise.then(this.tryTransitionToSection_.bind(this)); | 81 promise.then(this.tryTransitionToSection_.bind(this)); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 if (!canAnimateCollapse) { | 183 if (!canAnimateCollapse) { |
206 // Finish by restoring the section into the page. | 184 // Finish by restoring the section into the page. |
207 section.setFrozen(false); | 185 section.setFrozen(false); |
208 return Promise.resolve(); | 186 return Promise.resolve(); |
209 } | 187 } |
210 | 188 |
211 // Play the actual collapse animation. | 189 // Play the actual collapse animation. |
212 return new Promise(function(resolve, reject) { | 190 return new Promise(function(resolve, reject) { |
213 // Wait for the other sections to show up so we can scroll properly. | 191 // Wait for the other sections to show up so we can scroll properly. |
214 setTimeout(function() { | 192 setTimeout(function() { |
215 var newSection = settings.getCurrentRoute().section && | 193 var currentRoute = settings.getCurrentRoute(); |
216 this.getSection(settings.getCurrentRoute().section); | 194 var newSection = |
| 195 currentRoute.section && this.getSection(currentRoute.section); |
217 | 196 |
218 // Scroll to the section if indicated by the route. TODO(michaelpg): Is | 197 // Scroll to the new section if it's on this page. If the route has no |
219 // this the right behavior, or should we return to the previous scroll | 198 // section (e.g., a root page), return to the original position. |
220 // position? | |
221 if (newSection) | 199 if (newSection) |
222 newSection.scrollIntoView(); | 200 newSection.scrollIntoView(); |
223 else | 201 else if (!currentRoute.section) |
224 this.scroller.scrollTop = this.origScrollTop_; | 202 this.scroller.scrollTop = this.origScrollTop_; |
225 | 203 |
226 this.currentAnimation_ = section.animateCollapse( | 204 this.currentAnimation_ = section.animateCollapse( |
227 /** @type {!HTMLElement} */(this.scroller)); | 205 /** @type {!HTMLElement} */(this.scroller)); |
228 | 206 |
229 this.currentAnimation_.finished.catch(function() { | 207 this.currentAnimation_.finished.catch(function() { |
230 // The collapse was canceled, so the page is showing a subpage still. | 208 // The collapse was canceled, so the page is showing a subpage still. |
231 this.fire('subpage-expand'); | 209 this.fire('subpage-expand'); |
232 }.bind(this)).then(function() { | 210 }.bind(this)).then(function() { |
233 // Clean up after the animation succeeds or cancels. | 211 // Clean up after the animation succeeds or cancels. |
234 section.setFrozen(false); | 212 section.setFrozen(false); |
235 section.classList.remove('collapsing'); | 213 section.classList.remove('collapsing'); |
236 this.toggleScrolling_(true); | 214 this.toggleScrolling_(true); |
237 this.currentAnimation_ = null; | 215 this.currentAnimation_ = null; |
238 resolve(); | 216 resolve(); |
239 }.bind(this)); | 217 }.bind(this)); |
240 }.bind(this)); | 218 }.bind(this)); |
241 }.bind(this)); | 219 }.bind(this)); |
242 }, | 220 }, |
243 | 221 |
244 /** @private */ | 222 /** @private */ |
245 scrollToSection_: function() { | 223 scrollToSection_: function() { |
246 doWhenReady( | 224 assert(this.scrollHeight > 0); |
247 function() { | 225 var section = this.getSection(settings.getCurrentRoute().section); |
248 return this.scrollHeight > 0; | 226 assert(section); |
249 }.bind(this), | 227 section.scrollIntoView(); |
250 function() { | |
251 // If the current section changes while we are waiting for the page to | |
252 // be ready, scroll to the newest requested section. | |
253 var section = this.getSection(settings.getCurrentRoute().section); | |
254 if (section) | |
255 section.scrollIntoView(); | |
256 }.bind(this)); | |
257 }, | 228 }, |
258 | 229 |
259 /** | 230 /** |
260 /** | 231 /** |
261 * Hides or unhides the sections not being expanded. | 232 * Hides or unhides the sections not being expanded. |
262 * @param {string} sectionName The section to keep visible. | 233 * @param {string} sectionName The section to keep visible. |
263 * @param {boolean} hidden Whether the sections should be hidden. | 234 * @param {boolean} hidden Whether the sections should be hidden. |
264 * @private | 235 * @private |
265 */ | 236 */ |
266 toggleOtherSectionsHidden_: function(sectionName, hidden) { | 237 toggleOtherSectionsHidden_: function(sectionName, hidden) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)'; | 271 this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)'; |
301 } | 272 } |
302 } | 273 } |
303 }; | 274 }; |
304 | 275 |
305 /** @polymerBehavior */ | 276 /** @polymerBehavior */ |
306 var MainPageBehavior = [ | 277 var MainPageBehavior = [ |
307 settings.RouteObserverBehavior, | 278 settings.RouteObserverBehavior, |
308 MainPageBehaviorImpl, | 279 MainPageBehaviorImpl, |
309 ]; | 280 ]; |
OLD | NEW |