| 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 // Fast out, slow in. | 5 // Fast out, slow in. |
| 6 var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)'; | 6 var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)'; |
| 7 var EXPAND_DURATION = 350; | 7 var EXPAND_DURATION = 350; |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Workaround for scrolling an element into view when using Polymer. |
| 11 * @param {function():Element} containerCallback Return parent of element. |
| 12 * @param {function():Element} elementCallback Return element to scroll to. |
| 13 */ |
| 14 function scrollWhenReady(containerCallback, elementCallback) { |
| 15 // TODO(dschuyler): Determine whether this setTimeout can be removed. |
| 16 // See also: https://github.com/Polymer/polymer/issues/3629 |
| 17 setTimeout(function pollForScrollHeight() { |
| 18 var container = containerCallback(); |
| 19 if (!container || container.scrollHeight == 0) { |
| 20 setTimeout(pollForScrollHeight.bind(this), 10); |
| 21 return; |
| 22 } |
| 23 |
| 24 elementCallback().scrollIntoView(); |
| 25 }.bind(this)); |
| 26 } |
| 27 |
| 28 /** |
| 10 * Provides animations to expand and collapse individual sections in a page. | 29 * Provides animations to expand and collapse individual sections in a page. |
| 11 * Expanded sections take up the full height of the container. At most one | 30 * Expanded sections take up the full height of the container. At most one |
| 12 * section should be expanded at any given time. | 31 * section should be expanded at any given time. |
| 13 * @polymerBehavior Polymer.MainPageBehavior | 32 * @polymerBehavior Polymer.MainPageBehavior |
| 14 */ | 33 */ |
| 15 var MainPageBehaviorImpl = { | 34 var MainPageBehaviorImpl = { |
| 16 /** | 35 /** |
| 17 * @type {string} Selector to get the sections. Derived elements | 36 * @type {string} Selector to get the sections. Derived elements |
| 18 * must override. | 37 * must override. |
| 19 */ | 38 */ |
| 20 sectionSelector: '', | 39 sectionSelector: '', |
| 21 | 40 |
| 22 /** @type {?Element} The scrolling container. Elements must set this. */ | 41 /** @type {?Element} The scrolling container. */ |
| 23 scroller: null, | 42 scroller: null, |
| 24 | 43 |
| 44 /** @override */ |
| 45 attached: function() { |
| 46 this.scroller = this.domHost && this.domHost.parentNode.$.mainContainer; |
| 47 }, |
| 48 |
| 25 /** | 49 /** |
| 26 * Hides or unhides the sections not being expanded. | 50 * Hides or unhides the sections not being expanded. |
| 27 * @param {string} sectionName The section to keep visible. | 51 * @param {string} sectionName The section to keep visible. |
| 28 * @param {boolean} hidden Whether the sections should be hidden. | 52 * @param {boolean} hidden Whether the sections should be hidden. |
| 29 * @private | 53 * @private |
| 30 */ | 54 */ |
| 31 toggleOtherSectionsHidden_: function(sectionName, hidden) { | 55 toggleOtherSectionsHidden_: function(sectionName, hidden) { |
| 32 var sections = Polymer.dom(this.root).querySelectorAll( | 56 var sections = Polymer.dom(this.root).querySelectorAll( |
| 33 this.sectionSelector + ':not([section=' + sectionName + '])'); | 57 this.sectionSelector + ':not([section=' + sectionName + '])'); |
| 34 for (var section of sections) | 58 for (var section of sections) |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 /** | 229 /** |
| 206 * Expands the card in |section| to fill the page. | 230 * Expands the card in |section| to fill the page. |
| 207 * @param {!SettingsSectionElement} section | 231 * @param {!SettingsSectionElement} section |
| 208 * @return {!Promise} | 232 * @return {!Promise} |
| 209 * @private | 233 * @private |
| 210 */ | 234 */ |
| 211 playExpandSection_: function(section) { | 235 playExpandSection_: function(section) { |
| 212 var card = section.$.card; | 236 var card = section.$.card; |
| 213 | 237 |
| 214 // The card should start at the top of the page. | 238 // The card should start at the top of the page. |
| 215 var targetTop = this.parentElement.getBoundingClientRect().top; | 239 var targetTop = this.scroller.getBoundingClientRect().top; |
| 216 | 240 |
| 217 section.classList.add('expanding'); | 241 section.classList.add('expanding'); |
| 218 | 242 |
| 219 // Expand the card, using minHeight. (The card must span the container's | 243 // Expand the card, using minHeight. (The card must span the container's |
| 220 // client height, so it must be at least 100% in case the card is too short. | 244 // client height, so it must be at least 100% in case the card is too short. |
| 221 // If the card is already taller than the container's client height, we | 245 // If the card is already taller than the container's client height, we |
| 222 // don't want to shrink the card to 100% or the content will overflow, so | 246 // don't want to shrink the card to 100% or the content will overflow, so |
| 223 // we can't use height, and animating height wouldn't look right anyway.) | 247 // we can't use height, and animating height wouldn't look right anyway.) |
| 224 var keyframes = [{ | 248 var keyframes = [{ |
| 225 top: card.style.top, | 249 top: card.style.top, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 * @param {!SettingsSectionElement} section | 286 * @param {!SettingsSectionElement} section |
| 263 * @return {!Promise} | 287 * @return {!Promise} |
| 264 * @private | 288 * @private |
| 265 */ | 289 */ |
| 266 playCollapseSection_: function(section) { | 290 playCollapseSection_: function(section) { |
| 267 var card = section.$.card; | 291 var card = section.$.card; |
| 268 | 292 |
| 269 this.style.margin = ''; | 293 this.style.margin = ''; |
| 270 section.$.header.hidden = false; | 294 section.$.header.hidden = false; |
| 271 | 295 |
| 272 var startingTop = this.parentElement.getBoundingClientRect().top; | 296 var startingTop = this.scroller.getBoundingClientRect().top; |
| 273 | 297 |
| 274 var cardHeightStart = card.clientHeight; | 298 var cardHeightStart = card.clientHeight; |
| 275 var cardWidthStart = card.clientWidth; | 299 var cardWidthStart = card.clientWidth; |
| 276 | 300 |
| 277 section.classList.add('collapsing'); | 301 section.classList.add('collapsing'); |
| 278 section.classList.remove('expanding', 'expanded'); | 302 section.classList.remove('expanding', 'expanded'); |
| 279 | 303 |
| 280 // If we navigated here directly, we don't know the original height of the | 304 // If we navigated here directly, we don't know the original height of the |
| 281 // section, so we skip the animation. | 305 // section, so we skip the animation. |
| 282 // TODO(michaelpg): remove this condition once sliding is implemented. | 306 // TODO(michaelpg): remove this condition once sliding is implemented. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 /** Contains the current route. */ | 362 /** Contains the current route. */ |
| 339 currentRoute: { | 363 currentRoute: { |
| 340 type: Object, | 364 type: Object, |
| 341 notify: true, | 365 notify: true, |
| 342 observer: 'currentRouteChanged_', | 366 observer: 'currentRouteChanged_', |
| 343 }, | 367 }, |
| 344 }, | 368 }, |
| 345 | 369 |
| 346 /** @private */ | 370 /** @private */ |
| 347 scrollToSection_: function() { | 371 scrollToSection_: function() { |
| 348 // TODO(dschuyler): Determine whether this setTimeout can be removed. | 372 scrollWhenReady( |
| 349 // See also: https://github.com/Polymer/polymer/issues/3629 | 373 function() { |
| 350 setTimeout(function pollForScrollHeight() { | 374 return this; |
| 351 // If the current section changes while we are waiting for the page to be | 375 }.bind(this), |
| 352 // ready, scroll to the newest requested section. | 376 function() { |
| 353 var element = this.getSection_(this.currentRoute.section); | 377 // If the current section changes while we are waiting for the page to |
| 354 if (!element) | 378 // be ready, scroll to the newest requested section. |
| 355 return; | 379 return this.getSection_(this.currentRoute.section); |
| 356 | 380 }.bind(this)); |
| 357 var host = findAncestor(element, function(n) { return n.host; }).host; | |
| 358 if (host.scrollHeight == 0) { | |
| 359 setTimeout(pollForScrollHeight.bind(this), 100); | |
| 360 return; | |
| 361 } | |
| 362 | |
| 363 // TODO(michaelpg): due to the workaround for crbug.com/617827 in | |
| 364 // settings_page_css.html, we have to use element.offsetTop instead of | |
| 365 // relying on element.scrollIntoView() so the margin is included. | |
| 366 host.scroller.scrollTop = element.offsetTop; | |
| 367 }.bind(this)); | |
| 368 }, | 381 }, |
| 369 | 382 |
| 370 /** @private */ | 383 /** @private */ |
| 371 currentRouteChanged_: function(newRoute, oldRoute) { | 384 currentRouteChanged_: function(newRoute, oldRoute) { |
| 372 var newRouteIsSubpage = newRoute && newRoute.subpage.length; | 385 var newRouteIsSubpage = newRoute && newRoute.subpage.length; |
| 373 var oldRouteIsSubpage = oldRoute && oldRoute.subpage.length; | 386 var oldRouteIsSubpage = oldRoute && oldRoute.subpage.length; |
| 374 | 387 |
| 375 if (!oldRoute && newRouteIsSubpage) { | 388 if (!oldRoute && newRouteIsSubpage) { |
| 376 // Allow the page to load before expanding the section. TODO(michaelpg): | 389 // Allow the page to load before expanding the section. TODO(michaelpg): |
| 377 // Time this better when refactoring settings-animated-pages. | 390 // Time this better when refactoring settings-animated-pages. |
| 378 setTimeout(function() { | 391 setTimeout(function() { |
| 379 var section = this.getSection_(newRoute.section); | 392 var section = this.getSection_(newRoute.section); |
| 380 if (section) | 393 if (section) |
| 381 this.expandSection(section); | 394 this.expandSection(section); |
| 382 }.bind(this)); | 395 }.bind(this)); |
| 383 return; | 396 return; |
| 384 } | 397 } |
| 385 | 398 |
| 386 if (!newRouteIsSubpage && oldRouteIsSubpage) { | 399 if (!newRouteIsSubpage && oldRouteIsSubpage) { |
| 387 var section = this.getSection_(oldRoute.section); | 400 var section = this.getSection_(oldRoute.section); |
| 388 if (section) | 401 if (section) |
| 389 this.collapseSection(section); | 402 this.collapseSection(section); |
| 390 } else if (newRouteIsSubpage && | 403 } else if (newRouteIsSubpage && |
| 391 (!oldRouteIsSubpage || newRoute.section != oldRoute.section)) { | 404 (!oldRouteIsSubpage || newRoute.section != oldRoute.section)) { |
| 392 var section = this.getSection_(newRoute.section); | 405 var section = this.getSection_(newRoute.section); |
| 393 if (section) | 406 if (section) |
| 394 this.expandSection(section); | 407 this.expandSection(section); |
| 395 } else if (newRoute && newRoute.section) { | 408 } else if (newRoute && newRoute.section && |
| 409 this.$$('[data-page=' + newRoute.page + ']')) { |
| 396 this.scrollToSection_(); | 410 this.scrollToSection_(); |
| 397 } | 411 } |
| 398 }, | 412 }, |
| 399 | 413 |
| 400 /** | 414 /** |
| 401 * Helper function to get a section from the local DOM. | 415 * Helper function to get a section from the local DOM. |
| 402 * @param {string} section Section name of the element to get. | 416 * @param {string} section Section name of the element to get. |
| 403 * @return {?SettingsSectionElement} | 417 * @return {?SettingsSectionElement} |
| 404 * @private | 418 * @private |
| 405 */ | 419 */ |
| 406 getSection_: function(section) { | 420 getSection_: function(section) { |
| 407 return /** @type {?SettingsSectionElement} */( | 421 return /** @type {?SettingsSectionElement} */( |
| 408 this.$$('[section=' + section + ']')); | 422 this.$$('[section=' + section + ']')); |
| 409 }, | 423 }, |
| 410 }; | 424 }; |
| 411 | 425 |
| 412 | 426 |
| 413 /** @polymerBehavior */ | 427 /** @polymerBehavior */ |
| 414 var RoutableBehavior = [ | 428 var RoutableBehavior = [ |
| 415 MainPageBehavior, | 429 MainPageBehavior, |
| 416 RoutableBehaviorImpl | 430 RoutableBehaviorImpl |
| 417 ]; | 431 ]; |
| OLD | NEW |