| 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 * Responds to route changes by expanding, collapsing, or scrolling to sections | 6 * Responds to route changes by expanding, collapsing, or scrolling to sections |
| 7 * 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 |
| 8 * most one section should be expanded at any given time. | 8 * most one section should be expanded at any given time. |
| 9 * @polymerBehavior MainPageBehavior | 9 * @polymerBehavior MainPageBehavior |
| 10 */ | 10 */ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 }, | 23 }, |
| 24 | 24 |
| 25 /** @type {?HTMLElement} The scrolling container. */ | 25 /** @type {?HTMLElement} The scrolling container. */ |
| 26 scroller: null, | 26 scroller: null, |
| 27 | 27 |
| 28 /** @override */ | 28 /** @override */ |
| 29 attached: function() { | 29 attached: function() { |
| 30 if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL') | 30 if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL') |
| 31 this.scroller = this.domHost.parentNode.scroller; | 31 this.scroller = this.domHost.parentNode.scroller; |
| 32 else | 32 else |
| 33 this.scroller = document.body; // Used in unit tests. | 33 this.scroller = document.body; // Used in unit tests. |
| 34 }, | 34 }, |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * @param {!settings.Route} newRoute | 37 * @param {!settings.Route} newRoute |
| 38 * @param {settings.Route} oldRoute | 38 * @param {settings.Route} oldRoute |
| 39 */ | 39 */ |
| 40 currentRouteChanged: function(newRoute, oldRoute) { | 40 currentRouteChanged: function(newRoute, oldRoute) { |
| 41 var oldRouteWasSection = | 41 var oldRouteWasSection = !!oldRoute && !!oldRoute.parent && |
| 42 !!oldRoute && !!oldRoute.parent && !!oldRoute.section && | 42 !!oldRoute.section && oldRoute.parent.section != oldRoute.section; |
| 43 oldRoute.parent.section != oldRoute.section; | |
| 44 | 43 |
| 45 // Always scroll to the top if navigating from a section to the root route. | 44 // Always scroll to the top if navigating from a section to the root route. |
| 46 if (oldRouteWasSection && newRoute == settings.Route.BASIC) { | 45 if (oldRouteWasSection && newRoute == settings.Route.BASIC) { |
| 47 this.scroller.scrollTop = 0; | 46 this.scroller.scrollTop = 0; |
| 48 return; | 47 return; |
| 49 } | 48 } |
| 50 | 49 |
| 51 // Scroll to the section except for back/forward. Also scroll for any | 50 // Scroll to the section except for back/forward. Also scroll for any |
| 52 // in-page back/forward navigations (from a section or the root page). | 51 // in-page back/forward navigations (from a section or the root page). |
| 53 var scrollToSection = | 52 var scrollToSection = !settings.lastRouteChangeWasPopstate() || |
| 54 !settings.lastRouteChangeWasPopstate() || oldRouteWasSection || | 53 oldRouteWasSection || oldRoute == settings.Route.BASIC; |
| 55 oldRoute == settings.Route.BASIC; | |
| 56 | 54 |
| 57 // For previously uncreated pages (including on first load), allow the page | 55 // For previously uncreated pages (including on first load), allow the page |
| 58 // to render before scrolling to or expanding the section. | 56 // to render before scrolling to or expanding the section. |
| 59 if (!oldRoute || this.scrollHeight == 0) | 57 if (!oldRoute || this.scrollHeight == 0) |
| 60 setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); | 58 setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); |
| 61 else | 59 else |
| 62 this.tryTransitionToSection_(scrollToSection); | 60 this.tryTransitionToSection_(scrollToSection); |
| 63 }, | 61 }, |
| 64 | 62 |
| 65 /** | 63 /** |
| (...skipping 24 matching lines...) Expand all Loading... |
| 90 | 88 |
| 91 // If an animation is already playing, try finishing or canceling it. | 89 // If an animation is already playing, try finishing or canceling it. |
| 92 if (this.currentAnimation_) { | 90 if (this.currentAnimation_) { |
| 93 this.maybeStopCurrentAnimation_(); | 91 this.maybeStopCurrentAnimation_(); |
| 94 // Either way, this function will be called again once the current | 92 // Either way, this function will be called again once the current |
| 95 // animation ends. | 93 // animation ends. |
| 96 return; | 94 return; |
| 97 } | 95 } |
| 98 | 96 |
| 99 var promise; | 97 var promise; |
| 100 var expandedSection = /** @type {?SettingsSectionElement} */( | 98 var expandedSection = /** @type {?SettingsSectionElement} */ ( |
| 101 this.$$('settings-section.expanded')); | 99 this.$$('settings-section.expanded')); |
| 102 if (expandedSection) { | 100 if (expandedSection) { |
| 103 // If the section shouldn't be expanded, collapse it. | 101 // If the section shouldn't be expanded, collapse it. |
| 104 if (!currentRoute.isSubpage() || expandedSection != currentSection) { | 102 if (!currentRoute.isSubpage() || expandedSection != currentSection) { |
| 105 promise = this.collapseSection_(expandedSection); | 103 promise = this.collapseSection_(expandedSection); |
| 106 } else { | 104 } else { |
| 107 // Scroll to top while sliding to another subpage. | 105 // Scroll to top while sliding to another subpage. |
| 108 this.scroller.scrollTop = 0; | 106 this.scroller.scrollTop = 0; |
| 109 } | 107 } |
| 110 } else if (currentSection) { | 108 } else if (currentSection) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 121 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)); | 119 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)); |
| 122 }, | 120 }, |
| 123 | 121 |
| 124 /** | 122 /** |
| 125 * If the current animation is inconsistent with the current route, stops the | 123 * If the current animation is inconsistent with the current route, stops the |
| 126 * animation by finishing or canceling it so the new route can be animated to. | 124 * animation by finishing or canceling it so the new route can be animated to. |
| 127 * @private | 125 * @private |
| 128 */ | 126 */ |
| 129 maybeStopCurrentAnimation_: function() { | 127 maybeStopCurrentAnimation_: function() { |
| 130 var currentRoute = settings.getCurrentRoute(); | 128 var currentRoute = settings.getCurrentRoute(); |
| 131 var animatingSection = /** @type {?SettingsSectionElement} */( | 129 var animatingSection = /** @type {?SettingsSectionElement} */ ( |
| 132 this.$$('settings-section.expanding, settings-section.collapsing')); | 130 this.$$('settings-section.expanding, settings-section.collapsing')); |
| 133 assert(animatingSection); | 131 assert(animatingSection); |
| 134 | 132 |
| 135 if (animatingSection.classList.contains('expanding')) { | 133 if (animatingSection.classList.contains('expanding')) { |
| 136 // Cancel the animation to go back to the main page if the animating | 134 // Cancel the animation to go back to the main page if the animating |
| 137 // section shouldn't be expanded. | 135 // section shouldn't be expanded. |
| 138 if (animatingSection.section != currentRoute.section || | 136 if (animatingSection.section != currentRoute.section || |
| 139 !currentRoute.isSubpage()) { | 137 !currentRoute.isSubpage()) { |
| 140 this.currentAnimation_.cancel(); | 138 this.currentAnimation_.cancel(); |
| 141 } | 139 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 // Save the scroller position before freezing it. | 176 // Save the scroller position before freezing it. |
| 179 this.origScrollTop_ = this.scroller.scrollTop; | 177 this.origScrollTop_ = this.scroller.scrollTop; |
| 180 this.fire('freeze-scroll', true); | 178 this.fire('freeze-scroll', true); |
| 181 | 179 |
| 182 // Freeze the section's height so its card can be removed from the flow. | 180 // Freeze the section's height so its card can be removed from the flow. |
| 183 section.setFrozen(true); | 181 section.setFrozen(true); |
| 184 | 182 |
| 185 this.currentAnimation_ = section.animateExpand(this.scroller); | 183 this.currentAnimation_ = section.animateExpand(this.scroller); |
| 186 | 184 |
| 187 var finished; | 185 var finished; |
| 188 return this.currentAnimation_.finished.then(function() { | 186 return this.currentAnimation_.finished |
| 189 // Hide other sections and scroll to the top of the subpage. | 187 .then( |
| 190 this.classList.add('showing-subpage'); | 188 function() { |
| 191 this.toggleOtherSectionsHidden_(section.section, true); | 189 // Hide other sections and scroll to the top of the subpage. |
| 192 this.scroller.scrollTop = 0; | 190 this.classList.add('showing-subpage'); |
| 193 section.setFrozen(false); | 191 this.toggleOtherSectionsHidden_(section.section, true); |
| 192 this.scroller.scrollTop = 0; |
| 193 section.setFrozen(false); |
| 194 | 194 |
| 195 // Notify that the page is fully expanded. | 195 // Notify that the page is fully expanded. |
| 196 this.fire('subpage-expand'); | 196 this.fire('subpage-expand'); |
| 197 | 197 |
| 198 finished = true; | 198 finished = true; |
| 199 }.bind(this), function() { | 199 }.bind(this), |
| 200 // The animation was canceled; restore the section and scroll position. | 200 function() { |
| 201 section.setFrozen(false); | 201 // The animation was canceled; restore the section and scroll |
| 202 this.scroller.scrollTop = this.origScrollTop_; | 202 // position. |
| 203 section.setFrozen(false); |
| 204 this.scroller.scrollTop = this.origScrollTop_; |
| 203 | 205 |
| 204 finished = false; | 206 finished = false; |
| 205 }.bind(this)).then(function() { | 207 }.bind(this)) |
| 206 this.fire('freeze-scroll', false); | 208 .then(function() { |
| 207 this.currentAnimation_ = null; | 209 this.fire('freeze-scroll', false); |
| 208 }.bind(this)); | 210 this.currentAnimation_ = null; |
| 211 }.bind(this)); |
| 209 }, | 212 }, |
| 210 | 213 |
| 211 /** | 214 /** |
| 212 * Animates the card in |section|, collapsing it back into its section. | 215 * Animates the card in |section|, collapsing it back into its section. |
| 213 * @param {!SettingsSectionElement} section | 216 * @param {!SettingsSectionElement} section |
| 214 * @return {!Promise} Resolved when the transition is finished or canceled. | 217 * @return {!Promise} Resolved when the transition is finished or canceled. |
| 215 */ | 218 */ |
| 216 collapseSection_: function(section) { | 219 collapseSection_: function(section) { |
| 217 assert(this.scroller); | 220 assert(this.scroller); |
| 218 assert(section.classList.contains('expanded')); | 221 assert(section.classList.contains('expanded')); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 var newSection = settings.getCurrentRoute().section && | 255 var newSection = settings.getCurrentRoute().section && |
| 253 this.getSection(settings.getCurrentRoute().section); | 256 this.getSection(settings.getCurrentRoute().section); |
| 254 | 257 |
| 255 // Scroll to the new section or the original position. | 258 // Scroll to the new section or the original position. |
| 256 if (newSection && !settings.lastRouteChangeWasPopstate()) | 259 if (newSection && !settings.lastRouteChangeWasPopstate()) |
| 257 newSection.scrollIntoView(); | 260 newSection.scrollIntoView(); |
| 258 else | 261 else |
| 259 this.scroller.scrollTop = this.origScrollTop_; | 262 this.scroller.scrollTop = this.origScrollTop_; |
| 260 | 263 |
| 261 this.currentAnimation_ = section.animateCollapse( | 264 this.currentAnimation_ = section.animateCollapse( |
| 262 /** @type {!HTMLElement} */(this.scroller)); | 265 /** @type {!HTMLElement} */ (this.scroller)); |
| 263 | 266 |
| 264 this.currentAnimation_.finished.catch(function() { | 267 this.currentAnimation_.finished |
| 265 // The collapse was canceled, so the page is showing a subpage still. | 268 .catch(function() { |
| 266 this.fire('subpage-expand'); | 269 // The collapse was canceled, so the page is showing a subpage |
| 267 }.bind(this)).then(function() { | 270 // still. |
| 268 // Clean up after the animation succeeds or cancels. | 271 this.fire('subpage-expand'); |
| 269 section.setFrozen(false); | 272 }.bind(this)) |
| 270 section.classList.remove('collapsing'); | 273 .then(function() { |
| 271 this.fire('freeze-scroll', false); | 274 // Clean up after the animation succeeds or cancels. |
| 272 this.currentAnimation_ = null; | 275 section.setFrozen(false); |
| 273 resolve(); | 276 section.classList.remove('collapsing'); |
| 274 }.bind(this)); | 277 this.fire('freeze-scroll', false); |
| 278 this.currentAnimation_ = null; |
| 279 resolve(); |
| 280 }.bind(this)); |
| 275 }.bind(this)); | 281 }.bind(this)); |
| 276 }.bind(this)); | 282 }.bind(this)); |
| 277 }, | 283 }, |
| 278 | 284 |
| 279 /** | 285 /** |
| 280 /** | 286 /** |
| 281 * Hides or unhides the sections not being expanded. | 287 * Hides or unhides the sections not being expanded. |
| 282 * @param {string} sectionName The section to keep visible. | 288 * @param {string} sectionName The section to keep visible. |
| 283 * @param {boolean} hidden Whether the sections should be hidden. | 289 * @param {boolean} hidden Whether the sections should be hidden. |
| 284 * @private | 290 * @private |
| 285 */ | 291 */ |
| 286 toggleOtherSectionsHidden_: function(sectionName, hidden) { | 292 toggleOtherSectionsHidden_: function(sectionName, hidden) { |
| 287 var sections = Polymer.dom(this.root).querySelectorAll( | 293 var sections = Polymer.dom(this.root).querySelectorAll('settings-section'); |
| 288 'settings-section'); | |
| 289 for (var section of sections) | 294 for (var section of sections) |
| 290 section.hidden = hidden && (section.section != sectionName); | 295 section.hidden = hidden && (section.section != sectionName); |
| 291 }, | 296 }, |
| 292 | 297 |
| 293 /** | 298 /** |
| 294 * Helper function to get a section from the local DOM. | 299 * Helper function to get a section from the local DOM. |
| 295 * @param {string} section Section name of the element to get. | 300 * @param {string} section Section name of the element to get. |
| 296 * @return {?SettingsSectionElement} | 301 * @return {?SettingsSectionElement} |
| 297 */ | 302 */ |
| 298 getSection: function(section) { | 303 getSection: function(section) { |
| 299 if (!section) | 304 if (!section) |
| 300 return null; | 305 return null; |
| 301 return /** @type {?SettingsSectionElement} */( | 306 return /** @type {?SettingsSectionElement} */ ( |
| 302 this.$$('settings-section[section="' + section + '"]')); | 307 this.$$('settings-section[section="' + section + '"]')); |
| 303 }, | 308 }, |
| 304 }; | 309 }; |
| 305 | 310 |
| 306 /** @polymerBehavior */ | 311 /** @polymerBehavior */ |
| 307 var MainPageBehavior = [ | 312 var MainPageBehavior = [ |
| 308 settings.RouteObserverBehavior, | 313 settings.RouteObserverBehavior, |
| 309 MainPageBehaviorImpl, | 314 MainPageBehaviorImpl, |
| 310 ]; | 315 ]; |
| OLD | NEW |