| Index: chrome/browser/resources/settings/settings_page/settings_section.js
|
| diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js
|
| index e0e3afd11a6021b48301e9320e1f14bb1459b0fd..7833f39ba8b31db0bb47bbe0c20c88c58ed6ad2b 100644
|
| --- a/chrome/browser/resources/settings/settings_page/settings_section.js
|
| +++ b/chrome/browser/resources/settings/settings_page/settings_section.js
|
| @@ -16,10 +16,6 @@
|
| * </settings-section>
|
| */
|
|
|
| -// Fast out, slow in.
|
| -var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)';
|
| -var EXPAND_DURATION = 350;
|
| -
|
| var SettingsSectionElement = Polymer({
|
| is: 'settings-section',
|
|
|
| @@ -43,6 +39,18 @@ var SettingsSectionElement = Polymer({
|
| value: false,
|
| reflectToAttribute: true,
|
| },
|
| +
|
| + /**
|
| + * Original height of the collapsed section, used as the target height when
|
| + * collapsing after being expanded.
|
| + * TODO(michaelpg): Get the height dynamically when collapsing using the
|
| + * card's main page.
|
| + * @private
|
| + */
|
| + collapsedHeight_: {
|
| + type: Number,
|
| + value: NaN,
|
| + },
|
| },
|
|
|
| /**
|
| @@ -61,18 +69,9 @@ var SettingsSectionElement = Polymer({
|
| // If the section is not displayed yet (e.g., navigated directly to a
|
| // sub-page), cardHeight and cardWidth are 0, so do not set the height or
|
| // width explicitly.
|
| - // TODO(michaelpg): Improve this logic when refactoring
|
| - // settings-animated-pages.
|
| if (cardHeight && cardWidth) {
|
| - // TODO(michaelpg): Temporary hack to store the height the section
|
| - // should collapse to when it closes.
|
| - card.origHeight_ = cardHeight;
|
| -
|
| card.style.height = cardHeight + 'px';
|
| card.style.width = cardWidth + 'px';
|
| - } else {
|
| - // Set an invalid value so we don't try to use it later.
|
| - card.origHeight_ = NaN;
|
| }
|
|
|
| // Place the section's card at its current position but removed from the
|
| @@ -96,138 +95,158 @@ var SettingsSectionElement = Polymer({
|
| * already expanded or transitioning.
|
| */
|
| canAnimateExpand: function() {
|
| - return !this.classList.contains('expanded');
|
| + return !this.classList.contains('expanding') &&
|
| + !this.classList.contains('expanded') && this.$.card.clientHeight > 0;
|
| },
|
|
|
| /**
|
| * Animates the section expanding to fill the container. The section is fixed
|
| - * in the viewport during the animation. The section adds the "expanding"
|
| - * class while the animation plays.
|
| + * in the viewport during the animation, making it safe to adjust the rest of
|
| + * the DOM after calling this. The section adds the "expanding" class while
|
| + * the animation plays and "expanded" after it finishes.
|
| *
|
| * @param {!HTMLElement} container The scrolling container to fill.
|
| - * @return {?settings.animation.Animation} Animation played, if any.
|
| + * @return {!settings.animation.Animation}
|
| */
|
| animateExpand: function(container) {
|
| - var card = this.$.card;
|
| -
|
| - // The card should start at the top of the page.
|
| - var targetTop = container.getBoundingClientRect().top;
|
| + // Set the section's height so its card can be removed from the flow
|
| + // without affecting the surrounding sections during the animation.
|
| + this.collapsedHeight_ = this.clientHeight;
|
| + this.style.height = this.collapsedHeight_ + 'px';
|
|
|
| this.classList.add('expanding');
|
|
|
| - // Nothing to animate.
|
| - if (!card.style.top || !card.style.height)
|
| - return null;
|
| -
|
| - // Expand the card, using minHeight. (The card must span the container's
|
| - // client height, so it must be at least 100% in case the card is too short.
|
| - // If the card is already taller than the container's client height, we
|
| - // don't want to shrink the card to 100% or the content will overflow, so
|
| - // we can't use height, and animating height wouldn't look right anyway.)
|
| - var keyframes = [{
|
| - top: card.style.top,
|
| - minHeight: card.style.height,
|
| - easing: EASING_FUNCTION,
|
| - }, {
|
| - top: targetTop + 'px',
|
| - minHeight: 'calc(100% - ' + targetTop + 'px)',
|
| - }];
|
| - var options = /** @type {!KeyframeEffectOptions} */({
|
| - duration: EXPAND_DURATION
|
| - });
|
| - // TODO(michaelpg): Change elevation of sections.
|
| - return new settings.animation.Animation(card, keyframes, options);
|
| - },
|
| + // Start the card in place, at its distance from the container's padding.
|
| + var startTop = this.$.card.getBoundingClientRect().top + 'px';
|
| + var startHeight = this.$.card.clientHeight + 'px';
|
|
|
| - /**
|
| - * Cleans up after animateExpand().
|
| - * @param {boolean} finished Whether the animation finished successfully.
|
| - */
|
| - cleanUpAnimateExpand: function(finished) {
|
| - if (finished) {
|
| + // Target position is the container's top edge in the viewport.
|
| + var containerTop = container.getBoundingClientRect().top;
|
| + var endTop = containerTop + 'px';
|
| + // The card should stretch from the bottom of the toolbar to the bottom of
|
| + // the page. calc(100% - top) lets the card resize if the window resizes.
|
| + var endHeight = 'calc(100% - ' + containerTop + 'px)';
|
| +
|
| + var animation =
|
| + this.animateCard_('fixed', startTop, endTop, startHeight, endHeight);
|
| + animation.finished.then(function() {
|
| this.classList.add('expanded');
|
| - this.$.card.style.top = '';
|
| - this.$.header.hidden = true;
|
| + }.bind(this), function() {}).then(function() {
|
| + // Unset these changes whether the animation finished or canceled.
|
| + this.classList.remove('expanding');
|
| this.style.height = '';
|
| - }
|
| -
|
| - this.classList.remove('expanding');
|
| - this.$.card.style.height = '';
|
| - this.$.card.style.width = '';
|
| + }.bind(this));
|
| + return animation;
|
| },
|
|
|
| /** @return {boolean} True if the section is currently expanded. */
|
| canAnimateCollapse: function() {
|
| - return this.classList.contains('expanded');
|
| + return this.classList.contains('expanded') && this.clientHeight > 0 &&
|
| + !Number.isNaN(this.collapsedHeight_);
|
| + },
|
| +
|
| + /**
|
| + * Prepares for the animation before the other sections become visible.
|
| + * Call before animateCollapse().
|
| + * @param {!HTMLElement} container
|
| + */
|
| + setUpAnimateCollapse: function(container) {
|
| + // Prepare the dimensions and set position: fixed.
|
| + this.$.card.style.width = this.$.card.clientWidth + 'px';
|
| + this.$.card.style.height = this.$.card.clientHeight + 'px';
|
| + this.$.card.style.top = container.getBoundingClientRect().top + 'px';
|
| + this.$.card.style.position = 'fixed';
|
| +
|
| + // The section can now collapse back into its original height the page so
|
| + // the other sections appear in the right places.
|
| + this.classList.remove('expanded');
|
| + this.classList.add('collapsing');
|
| + this.style.height = this.collapsedHeight_ + 'px';
|
| },
|
|
|
| /**
|
| * Collapses an expanded section's card back into position in the main page.
|
| - * Adds the "expanding" class during the animation.
|
| + * Call after calling animateCollapse(), unhiding other content and scrolling.
|
| * @param {!HTMLElement} container The scrolling container the card fills.
|
| - * @param {number} prevScrollTop scrollTop of the container before this
|
| - * section expanded.
|
| - * @return {?settings.animation.Animation} Animation played, if any.
|
| + * @return {!settings.animation.Animation}
|
| */
|
| - animateCollapse: function(container, prevScrollTop) {
|
| - this.$.header.hidden = false;
|
| + animateCollapse: function(container) {
|
| + // Make the card position: absolute, so scrolling is less of a crapshoot.
|
| + // First find the current distance between this section and the card using
|
| + // fixed coordinates; the absolute distance will be the same.
|
| + var fixedCardTop = this.$.card.getBoundingClientRect().top;
|
| + var fixedSectionTop = this.getBoundingClientRect().top;
|
| + var distance = fixedCardTop - fixedSectionTop;
|
| +
|
| + // The target position is right below our header.
|
| + var headerStyle = getComputedStyle(this.$.header);
|
| + var cardTargetTop = this.$.header.offsetHeight +
|
| + parseFloat(headerStyle.marginBottom) +
|
| + parseFloat(headerStyle.marginTop);
|
|
|
| - var startingTop = container.getBoundingClientRect().top;
|
| + // Start the card at its current height and distance from our top.
|
| + var startTop = distance + 'px';
|
| + var startHeight = this.$.card.style.height;
|
|
|
| - var card = this.$.card;
|
| - var cardHeightStart = card.clientHeight;
|
| - var cardWidthStart = card.clientWidth;
|
| + // End at the bottom of our header.
|
| + var endTop = cardTargetTop + 'px';
|
| + var endHeight = (this.collapsedHeight_ - cardTargetTop) + 'px';
|
|
|
| - this.classList.add('collapsing');
|
| - this.classList.remove('expanding', 'expanded');
|
| + // The card no longer needs position: fixed.
|
| + this.$.card.style.position = '';
|
|
|
| - // If we navigated here directly, we don't know the original height of the
|
| - // section, so we skip the animation.
|
| - // TODO(michaelpg): remove this condition once sliding is implemented.
|
| - if (Number.isNaN(card.origHeight_))
|
| - return null;
|
| -
|
| - // Restore the section to its proper height to make room for the card.
|
| - this.style.height = (this.clientHeight + card.origHeight_) + 'px';
|
| + // Collapse this section, animate the card into place, and remove its
|
| + // other properties.
|
| + var animation =
|
| + this.animateCard_('absolute', startTop, endTop, startHeight, endHeight);
|
| + this.$.card.style.width = '';
|
| + this.$.card.style.height = '';
|
| + this.$.card.style.top = '';
|
|
|
| - // TODO(michaelpg): this should be in MainPageBehavior(), but we need to
|
| - // wait until the full page height is available (setting the section
|
| - // height).
|
| - container.scrollTop = prevScrollTop;
|
| + animation.finished.then(function() {
|
| + this.classList.remove('expanded');
|
| + }.bind(this), function() {}).then(function() {
|
| + // The card now determines the section's height automatically.
|
| + this.style.height = '';
|
| + this.classList.remove('collapsing');
|
| + }.bind(this));
|
| + return animation;
|
| + },
|
|
|
| - // The card is unpositioned, so use its position as the ending state,
|
| - // but account for scroll.
|
| - var targetTop = card.getBoundingClientRect().top - container.scrollTop;
|
| + /**
|
| + * Helper function to animate the card's position and height.
|
| + * @param {string} position CSS position property.
|
| + * @param {string} startTop Initial top value.
|
| + * @param {string} endTop Target top value.
|
| + * @param {string} startHeight Initial height value.
|
| + * @param {string} endHeight Target height value.
|
| + * @return {!settings.animation.Animation}
|
| + * @private
|
| + */
|
| + animateCard_: function(position, startTop, endTop, startHeight, endHeight) {
|
| + // Width does not change.
|
| + var width = this.$.card.clientWidth + 'px';
|
| +
|
| + var startFrame = {
|
| + position: position,
|
| + width: width,
|
| + top: startTop,
|
| + height: startHeight,
|
| + };
|
| +
|
| + var endFrame = {
|
| + position: position,
|
| + width: width,
|
| + top: endTop,
|
| + height: endHeight,
|
| + };
|
|
|
| - // Account for the section header.
|
| - var headerStyle = getComputedStyle(this.$.header);
|
| - targetTop += this.$.header.offsetHeight +
|
| - parseInt(headerStyle.marginBottom, 10) +
|
| - parseInt(headerStyle.marginTop, 10);
|
| -
|
| - var keyframes = [{
|
| - top: startingTop + 'px',
|
| - minHeight: cardHeightStart + 'px',
|
| - easing: EASING_FUNCTION,
|
| - }, {
|
| - top: targetTop + 'px',
|
| - minHeight: card.origHeight_ + 'px',
|
| - }];
|
| var options = /** @type {!KeyframeEffectOptions} */({
|
| - duration: EXPAND_DURATION
|
| + duration: settings.animation.Timing.DURATION,
|
| + easing: settings.animation.Timing.EASING,
|
| });
|
|
|
| - card.style.width = cardWidthStart + 'px';
|
| -
|
| - return new settings.animation.Animation(card, keyframes, options);
|
| - },
|
| -
|
| - /**
|
| - * Cleans up after animateCollapse().
|
| - * @param {boolean} finished Whether the animation finished successfully.
|
| - */
|
| - cleanUpAnimateCollapse: function(finished) {
|
| - if (finished)
|
| - this.$.card.style.width = '';
|
| + return new settings.animation.Animation(
|
| + this.$.card, [startFrame, endFrame], options);
|
| },
|
| });
|
|
|