| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 // TODO(dschuyler): This doesn't set the flag in the case of going to or | 86 // TODO(dschuyler): This doesn't set the flag in the case of going to or |
| 87 // from the main page. It seems sensible to set the flag in those cases, | 87 // from the main page. It seems sensible to set the flag in those cases, |
| 88 // unfortunately bug 708465 happens. Figure out why that is and then set | 88 // unfortunately bug 708465 happens. Figure out why that is and then set |
| 89 // this flag more broadly. | 89 // this flag more broadly. |
| 90 if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage()) | 90 if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage()) |
| 91 this.isSubpageAnimating = true; | 91 this.isSubpageAnimating = true; |
| 92 | 92 |
| 93 // For previously uncreated pages (including on first load), allow the page | 93 // For previously uncreated pages (including on first load), allow the page |
| 94 // to render before scrolling to or expanding the section. | 94 // to render before scrolling to or expanding the section. |
| 95 if (!oldRoute || this.scrollHeight == 0) | 95 if (!oldRoute) { |
| 96 this.fire('hide-container'); |
| 97 setTimeout(function() { |
| 98 this.fire('show-container'); |
| 99 this.tryTransitionToSection_(scrollToSection, true); |
| 100 }.bind(this)); |
| 101 } else if (this.scrollHeight == 0) { |
| 96 setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); | 102 setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); |
| 97 else | 103 } else { |
| 98 this.tryTransitionToSection_(scrollToSection); | 104 this.tryTransitionToSection_(scrollToSection); |
| 105 } |
| 99 }, | 106 }, |
| 100 | 107 |
| 101 /** | 108 /** |
| 102 * When exiting search mode, we need to make another attempt to scroll to | 109 * When exiting search mode, we need to make another attempt to scroll to |
| 103 * the correct section, since it has just been re-rendered. | 110 * the correct section, since it has just been re-rendered. |
| 104 * @private | 111 * @private |
| 105 */ | 112 */ |
| 106 inSearchModeChanged_: function(inSearchMode) { | 113 inSearchModeChanged_: function(inSearchMode) { |
| 107 if (!this.isAttached) | 114 if (!this.isAttached) |
| 108 return; | 115 return; |
| 109 | 116 |
| 110 if (!inSearchMode) | 117 if (!inSearchMode) |
| 111 this.tryTransitionToSection_(!settings.lastRouteChangeWasPopstate()); | 118 this.tryTransitionToSection_(!settings.lastRouteChangeWasPopstate()); |
| 112 }, | 119 }, |
| 113 | 120 |
| 114 /** | 121 /** |
| 115 * If possible, transitions to the current route's section (by expanding or | 122 * If possible, transitions to the current route's section (by expanding or |
| 116 * scrolling to it). If another transition is running, finishes or cancels | 123 * scrolling to it). If another transition is running, finishes or cancels |
| 117 * that one, then schedules this function again. This ensures the current | 124 * that one, then schedules this function again. This ensures the current |
| 118 * section is quickly shown, without getting the page into a broken state -- | 125 * section is quickly shown, without getting the page into a broken state -- |
| 119 * if currentRoute changes in between calls, just transition to the new route. | 126 * if currentRoute changes in between calls, just transition to the new route. |
| 120 * @param {boolean} scrollToSection | 127 * @param {boolean} scrollToSection |
| 128 * @param {boolean=} immediate Whether to instantly expand instead of animate. |
| 121 * @private | 129 * @private |
| 122 */ | 130 */ |
| 123 tryTransitionToSection_: function(scrollToSection) { | 131 tryTransitionToSection_: function(scrollToSection, immediate) { |
| 124 var currentRoute = settings.getCurrentRoute(); | 132 var currentRoute = settings.getCurrentRoute(); |
| 125 var currentSection = this.getSection(currentRoute.section); | 133 var currentSection = this.getSection(currentRoute.section); |
| 126 | 134 |
| 127 // If an animation is already playing, try finishing or canceling it. | 135 // If an animation is already playing, try finishing or canceling it. |
| 128 if (this.currentAnimation_) { | 136 if (this.currentAnimation_) { |
| 129 this.maybeStopCurrentAnimation_(); | 137 this.maybeStopCurrentAnimation_(); |
| 130 // Either way, this function will be called again once the current | 138 // Either way, this function will be called again once the current |
| 131 // animation ends. | 139 // animation ends. |
| 132 return; | 140 return; |
| 133 } | 141 } |
| 134 | 142 |
| 135 var promise; | 143 var promise; |
| 136 var expandedSection = /** @type {?SettingsSectionElement} */( | 144 var expandedSection = /** @type {?SettingsSectionElement} */( |
| 137 this.$$('settings-section.expanded')); | 145 this.$$('settings-section.expanded')); |
| 138 if (expandedSection) { | 146 if (expandedSection) { |
| 139 // If the section shouldn't be expanded, collapse it. | 147 // If the section shouldn't be expanded, collapse it. |
| 140 if (!currentRoute.isSubpage() || expandedSection != currentSection) { | 148 if (!currentRoute.isSubpage() || expandedSection != currentSection) { |
| 141 promise = this.collapseSection_(expandedSection); | 149 promise = this.collapseSection_(expandedSection); |
| 142 } else { | 150 } else { |
| 143 // Scroll to top while sliding to another subpage. | 151 // Scroll to top while sliding to another subpage. |
| 144 this.scroller.scrollTop = 0; | 152 this.scroller.scrollTop = 0; |
| 145 } | 153 } |
| 146 } else if (currentSection) { | 154 } else if (currentSection) { |
| 147 // Expand the section into a subpage or scroll to it on the main page. | 155 // Expand the section into a subpage or scroll to it on the main page. |
| 148 if (currentRoute.isSubpage()) | 156 if (currentRoute.isSubpage()) { |
| 149 promise = this.expandSection_(currentSection); | 157 if (immediate) |
| 150 else if (scrollToSection) | 158 this.expandSectionImmediate_(currentSection); |
| 159 else |
| 160 promise = this.expandSection_(currentSection); |
| 161 } else if (scrollToSection) { |
| 151 currentSection.scrollIntoView(); | 162 currentSection.scrollIntoView(); |
| 163 } |
| 152 } else if ( | 164 } else if ( |
| 153 this.tagName == 'SETTINGS-BASIC-PAGE' && | 165 this.tagName == 'SETTINGS-BASIC-PAGE' && |
| 154 settings.Route.ADVANCED.contains(currentRoute) && | 166 settings.Route.ADVANCED.contains(currentRoute) && |
| 155 // Need to exclude routes that correspond to 'non-sectioned' children of | 167 // Need to exclude routes that correspond to 'non-sectioned' children of |
| 156 // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly. | 168 // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly. |
| 157 !currentRoute.isNavigableDialog) { | 169 !currentRoute.isNavigableDialog) { |
| 158 assert(currentRoute.section); | 170 assert(currentRoute.section); |
| 171 // Hide the container again while Advanced Page template is being loaded. |
| 172 this.fire('hide-container'); |
| 159 promise = this.$$('#advancedPageTemplate').get(); | 173 promise = this.$$('#advancedPageTemplate').get(); |
| 160 } | 174 } |
| 161 | 175 |
| 162 // When this animation ends, another may be necessary. Call this function | 176 // When this animation ends, another may be necessary. Call this function |
| 163 // again after the promise resolves. | 177 // again after the promise resolves. |
| 164 if (promise) | 178 if (promise) { |
| 165 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)); | 179 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)) |
| 180 .then(function() { |
| 181 this.fire('show-container'); |
| 182 }.bind(this)); |
| 183 } |
| 166 }, | 184 }, |
| 167 | 185 |
| 168 /** | 186 /** |
| 169 * If the current animation is inconsistent with the current route, stops the | 187 * If the current animation is inconsistent with the current route, stops the |
| 170 * animation by finishing or canceling it so the new route can be animated to. | 188 * animation by finishing or canceling it so the new route can be animated to. |
| 171 * @private | 189 * @private |
| 172 */ | 190 */ |
| 173 maybeStopCurrentAnimation_: function() { | 191 maybeStopCurrentAnimation_: function() { |
| 174 var currentRoute = settings.getCurrentRoute(); | 192 var currentRoute = settings.getCurrentRoute(); |
| 175 var animatingSection = /** @type {?SettingsSectionElement} */( | 193 var animatingSection = /** @type {?SettingsSectionElement} */( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 197 this.currentAnimation_.cancel(); | 215 this.currentAnimation_.cancel(); |
| 198 return; | 216 return; |
| 199 } | 217 } |
| 200 | 218 |
| 201 // The current route is a subpage, so that section needs to expand. | 219 // The current route is a subpage, so that section needs to expand. |
| 202 // Immediately finish the current collapse animation so that can happen. | 220 // Immediately finish the current collapse animation so that can happen. |
| 203 this.currentAnimation_.finish(); | 221 this.currentAnimation_.finish(); |
| 204 }, | 222 }, |
| 205 | 223 |
| 206 /** | 224 /** |
| 225 * Immediately expand the card in |section| to fill the page. |
| 226 * @param {!SettingsSectionElement} section |
| 227 * @private |
| 228 */ |
| 229 expandSectionImmediate_: function(section) { |
| 230 assert(this.scroller); |
| 231 section.immediateExpand(this.scroller); |
| 232 this.finishedExpanding_(section); |
| 233 // TODO(scottchen): iron-list inside subpages need this to render correctly. |
| 234 this.fire('resize'); |
| 235 }, |
| 236 |
| 237 /** |
| 207 * Animates the card in |section|, expanding it to fill the page. | 238 * Animates the card in |section|, expanding it to fill the page. |
| 208 * @param {!SettingsSectionElement} section | 239 * @param {!SettingsSectionElement} section |
| 209 * @return {!Promise} Resolved when the transition is finished or canceled. | 240 * @return {!Promise} Resolved when the transition is finished or canceled. |
| 210 * @private | 241 * @private |
| 211 */ | 242 */ |
| 212 expandSection_: function(section) { | 243 expandSection_: function(section) { |
| 213 assert(this.scroller); | 244 assert(this.scroller); |
| 214 | |
| 215 if (!section.canAnimateExpand()) { | 245 if (!section.canAnimateExpand()) { |
| 216 // Try to wait for the section to be created. | 246 // Try to wait for the section to be created. |
| 217 return new Promise(function(resolve, reject) { | 247 return new Promise(function(resolve, reject) { |
| 218 setTimeout(resolve); | 248 setTimeout(resolve); |
| 219 }); | 249 }); |
| 220 } | 250 } |
| 221 | 251 |
| 222 // Save the scroller position before freezing it. | 252 // Save the scroller position before freezing it. |
| 223 this.origScrollTop_ = this.scroller.scrollTop; | 253 this.origScrollTop_ = this.scroller.scrollTop; |
| 224 this.fire('freeze-scroll', true); | 254 this.fire('freeze-scroll', true); |
| 225 | 255 |
| 226 // Freeze the section's height so its card can be removed from the flow. | 256 // Freeze the section's height so its card can be removed from the flow. |
| 227 section.setFrozen(true); | 257 section.setFrozen(true); |
| 228 | 258 |
| 229 this.currentAnimation_ = section.animateExpand(this.scroller); | 259 this.currentAnimation_ = section.animateExpand(this.scroller); |
| 230 | 260 |
| 231 var finished; | 261 return this.currentAnimation_.finished |
| 232 return this.currentAnimation_.finished.then(function() { | 262 .then( |
| 233 // Hide other sections and scroll to the top of the subpage. | 263 function() { |
| 234 this.classList.add('showing-subpage'); | 264 this.finishedExpanding_(section); |
| 235 this.toggleOtherSectionsHidden_(section.section, true); | 265 }.bind(this), |
| 236 this.scroller.scrollTop = 0; | 266 function() { |
| 237 section.setFrozen(false); | 267 // The animation was canceled; restore the section and scroll |
| 268 // position. |
| 269 section.setFrozen(false); |
| 270 this.scroller.scrollTop = this.origScrollTop_; |
| 271 }.bind(this)) |
| 272 .then(function() { |
| 273 this.fire('freeze-scroll', false); |
| 274 this.currentAnimation_ = null; |
| 275 }.bind(this)); |
| 276 }, |
| 238 | 277 |
| 239 // Notify that the page is fully expanded. | 278 /** @private */ |
| 240 this.fire('subpage-expand'); | 279 finishedExpanding_: function(section) { |
| 280 // Hide other sections and scroll to the top of the subpage. |
| 281 this.classList.add('showing-subpage'); |
| 282 this.toggleOtherSectionsHidden_(section.section, true); |
| 283 this.scroller.scrollTop = 0; |
| 284 section.setFrozen(false); |
| 241 | 285 |
| 242 finished = true; | 286 // Notify that the page is fully expanded. |
| 243 }.bind(this), function() { | 287 this.fire('subpage-expand'); |
| 244 // The animation was canceled; restore the section and scroll position. | |
| 245 section.setFrozen(false); | |
| 246 this.scroller.scrollTop = this.origScrollTop_; | |
| 247 | |
| 248 finished = false; | |
| 249 }.bind(this)).then(function() { | |
| 250 this.fire('freeze-scroll', false); | |
| 251 this.currentAnimation_ = null; | |
| 252 }.bind(this)); | |
| 253 }, | 288 }, |
| 254 | 289 |
| 255 /** | 290 /** |
| 256 * Animates the card in |section|, collapsing it back into its section. | 291 * Animates the card in |section|, collapsing it back into its section. |
| 257 * @param {!SettingsSectionElement} section | 292 * @param {!SettingsSectionElement} section |
| 258 * @return {!Promise} Resolved when the transition is finished or canceled. | 293 * @return {!Promise} Resolved when the transition is finished or canceled. |
| 259 */ | 294 */ |
| 260 collapseSection_: function(section) { | 295 collapseSection_: function(section) { |
| 261 assert(this.scroller); | 296 assert(this.scroller); |
| 262 assert(section.classList.contains('expanded')); | 297 assert(section.classList.contains('expanded')); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 return /** @type {?SettingsSectionElement} */( | 382 return /** @type {?SettingsSectionElement} */( |
| 348 this.$$('settings-section[section="' + section + '"]')); | 383 this.$$('settings-section[section="' + section + '"]')); |
| 349 }, | 384 }, |
| 350 }; | 385 }; |
| 351 | 386 |
| 352 /** @polymerBehavior */ | 387 /** @polymerBehavior */ |
| 353 var MainPageBehavior = [ | 388 var MainPageBehavior = [ |
| 354 settings.RouteObserverBehavior, | 389 settings.RouteObserverBehavior, |
| 355 MainPageBehaviorImpl, | 390 MainPageBehaviorImpl, |
| 356 ]; | 391 ]; |
| OLD | NEW |