Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1633)

Unified Diff: chrome/browser/resources/settings/settings_page/main_page_behavior.js

Issue 2106013002: Move settings-section animations into setting-section, make better (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@Transitions
Patch Set: Reworked properties/rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/settings/settings_page/main_page_behavior.js
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
index 4b6442c44c82c15ddccf7898de684603d1012755..4912855ca36ae6a847977c8c13028d79f241a915 100644
--- a/chrome/browser/resources/settings/settings_page/main_page_behavior.js
+++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Fast out, slow in.
-var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)';
-var EXPAND_DURATION = 350;
-
/**
* Calls |readyTest| repeatedly until it returns true, then calls
* |readyCallback|.
@@ -36,11 +32,9 @@ var MainPageBehaviorImpl = {
*/
sectionSelector: '',
- /** @type {?Element} The scrolling container. */
- scroller: null,
-
/** @override */
attached: function() {
+ /** @type {!HTMLElement} The scrolling container. */
this.scroller = this.domHost && this.domHost.parentNode.$.mainContainer;
},
@@ -62,77 +56,57 @@ var MainPageBehaviorImpl = {
* @param {!SettingsSectionElement} section
*/
expandSection: function(section) {
- // If another section's card is expanding, cancel that animation first.
- var expanding = this.$$('.expanding');
- if (expanding) {
- if (expanding == section)
+ // TODO(michaelpg): Manage transition lifetime better.
+ // crbug.com/624145
+ if (this.openSectionTransition_) {
+ if (this.openSectionTransition_.section == section)
return;
- if (this.animations['section']) {
- // Cancel the animation, then call startExpandSection_.
- this.cancelAnimation('section', function() {
- this.startExpandSection_(section);
- }.bind(this));
- } else {
- // The animation must have finished but its promise hasn't resolved yet.
- // When it resolves, collapse that section's card before expanding
- // this one.
- setTimeout(function() {
- this.collapseSection(
- /** @type {!SettingsSectionElement} */(expanding));
- this.finishAnimation('section', function() {
- this.startExpandSection_(section);
- }.bind(this));
- }.bind(this));
- }
-
+ // Cancel the other section expanding.
+ this.openSectionTransition_.cancel();
+ // After everything, schedule this function again to open the section.
+ this.openSectionTransition_.finished
+ .then(function() {
+ // The animation already finished, so close that section.
+ this.collapseSection(this.openSectionTransition_.section);
+ }).catch(function() {})
dschuyler 2016/07/21 03:26:09 Does this .catch hide something specific? Maybe ad
michaelpg 2016/07/22 16:05:50 Removed now that AnimationGroup promises resolve o
+ .then(this.expandSection.bind(this, section));
return;
}
-
- if (this.$$('.collapsing') && this.animations['section']) {
- // Finish the collapse animation before expanding.
- this.finishAnimation('section', function() {
- this.startExpandSection_(section);
- }.bind(this));
+ if (this.closeSectionTransition_) {
+ // Finish collapsing the section, then expand this section.
+ this.closeSectionTransition_.finished.then(
+ this.expandSection.bind(this, section));
return;
}
- this.startExpandSection_(section);
- },
-
- /**
- * Helper function to set up and start the expand animation.
- * @param {!SettingsSectionElement} section
- */
- startExpandSection_: function(section) {
- if (section.classList.contains('expanded'))
- return;
+ this.openSectionTransition_ =
+ new settings.OpenSectionTransition(section, this.scroller);
// Freeze the scroller and save its position.
- this.listScrollTop_ = this.scroller.scrollTop;
-
+ this.scroller.listScrollTop_ = this.scroller.scrollTop;
var scrollerWidth = this.scroller.clientWidth;
this.scroller.style.overflow = 'hidden';
+
// Adjust width to compensate for scroller.
var scrollbarWidth = this.scroller.clientWidth - scrollerWidth;
this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)';
- // Freezes the section's height so its card can be removed from the flow.
- this.freezeSection_(section);
-
- // Expand the section's card to fill the parent.
- var animationPromise = this.playExpandSection_(section);
-
- animationPromise.then(function() {
- this.scroller.scrollTop = 0;
- this.toggleOtherSectionsHidden_(section.section, true);
- }.bind(this), function() {
- // Animation was canceled; restore the section.
- this.unfreezeSection_(section);
- }.bind(this)).then(function() {
- this.scroller.style.overflow = '';
- this.scroller.style.width = '';
- }.bind(this));
+ this.openSectionTransition_.play()
+ .then(function() {
+ this.toggleOtherSectionsHidden_(section.section, true);
+ this.scroller.scrollTop = 0;
+ this.classList.add('showing-subpage');
+ this.fire('subpage-expand');
+ }.bind(this))
+ .catch(function() {
+ this.scroller.scrollTop = this.scroller.listScrollTop_;
+ }.bind(this))
+ .then(function() {
+ this.scroller.style.width = '';
+ this.scroller.style.overflow = '';
+ this.openSectionTransition_ = null;
+ }.bind(this));
},
/**
@@ -140,213 +114,60 @@ var MainPageBehaviorImpl = {
* @param {!SettingsSectionElement} section
*/
collapseSection: function(section) {
- // If the section's card is still expanding, cancel the expand animation.
- if (section.classList.contains('expanding')) {
- if (this.animations['section']) {
- this.cancelAnimation('section');
- } else {
- // The animation must have finished but its promise hasn't finished
- // resolving; try again asynchronously.
- this.async(function() {
- this.collapseSection(section);
- });
- }
+ if (this.closeSectionTransition_) {
+ assert(this.closeSectionTransition_.section == section);
+ this.closeSectionTransition_.cancel();
return;
}
- if (!section.classList.contains('expanded'))
+ if (this.openSectionTransition_) {
+ assert(this.openSectionTransition_.section == section);
+ this.openSectionTransition_.cancel();
return;
+ }
- this.toggleOtherSectionsHidden_(section.section, false);
+ assert(section.classList.contains('expanded'));
var scrollerWidth = this.scroller.clientWidth;
this.scroller.style.overflow = 'hidden';
+
// Adjust width to compensate for scroller.
+ // TODO(michaelpg): Minimize horizontal motion when scrollbar changes for
+ // the common cases.
var scrollbarWidth = this.scroller.clientWidth - scrollerWidth;
this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)';
- this.playCollapseSection_(section).then(function() {
- this.unfreezeSection_(section);
- this.scroller.style.overflow = '';
- this.scroller.style.width = '';
- section.classList.remove('collapsing');
- }.bind(this));
- },
-
- /**
- * Freezes a section's height so its card can be removed from the flow without
- * affecting the layout of the surrounding sections.
- * @param {!SettingsSectionElement} section
- * @private
- */
- freezeSection_: function(section) {
- var card = section.$.card;
- section.style.height = section.clientHeight + 'px';
-
- var cardHeight = card.offsetHeight;
- var cardWidth = card.offsetWidth;
- // 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
- // flow.
- card.style.top = card.getBoundingClientRect().top + 'px';
- section.classList.add('frozen');
- },
-
- /**
- * After freezeSection_, restores the section to its normal height.
- * @param {!SettingsSectionElement} section
- * @private
- */
- unfreezeSection_: function(section) {
- if (!section.classList.contains('frozen'))
- return;
- var card = section.$.card;
- section.classList.remove('frozen');
- card.style.top = '';
- card.style.height = '';
- card.style.width = '';
- section.style.height = '';
- },
-
- /**
- * Expands the card in |section| to fill the page.
- * @param {!SettingsSectionElement} section
- * @return {!Promise}
- * @private
- */
- playExpandSection_: function(section) {
- var card = section.$.card;
-
- // The card should start at the top of the page.
- var targetTop = this.scroller.getBoundingClientRect().top;
-
- section.classList.add('expanding');
-
- // 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.
- var promise;
- if (keyframes[0].top && keyframes[0].minHeight)
- promise = this.animateElement('section', card, keyframes, options);
- else
- promise = Promise.resolve();
-
- promise.then(function() {
- section.classList.add('expanded');
- card.style.top = '';
- this.style.margin = 'auto';
- section.$.header.hidden = true;
- section.style.height = '';
- }.bind(this), function() {
- // The animation was canceled; catch the error and continue.
- }).then(function() {
- // Whether finished or canceled, clean up the animation.
- section.classList.remove('expanding');
- card.style.height = '';
- card.style.width = '';
- });
-
- return promise;
- },
-
- /**
- * Collapses the card in |section| back to its normal position.
- * @param {!SettingsSectionElement} section
- * @return {!Promise}
- * @private
- */
- playCollapseSection_: function(section) {
- var card = section.$.card;
-
- this.style.margin = '';
- section.$.header.hidden = false;
-
- var startingTop = this.scroller.getBoundingClientRect().top;
-
- var cardHeightStart = card.clientHeight;
- var cardWidthStart = card.clientWidth;
-
- section.classList.add('collapsing');
- section.classList.remove('expanding', 'expanded');
-
- // 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 (isNaN(card.origHeight_))
- return Promise.resolve();
-
- // Restore the section to its proper height to make room for the card.
- section.style.height = section.clientHeight + card.origHeight_ + 'px';
-
- // TODO(michaelpg): this should be in collapseSection(), but we need to wait
- // until the full page height is available (setting the section height).
- this.scroller.scrollTop = this.listScrollTop_;
-
- // The card is unpositioned, so use its position as the ending state,
- // but account for scroll.
- var targetTop = card.getBoundingClientRect().top - this.scroller.scrollTop;
-
- // Account for the section header.
- var headerStyle = getComputedStyle(section.$.header);
- targetTop += section.$.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
- });
-
- card.style.width = cardWidthStart + 'px';
- var promise = this.animateElement('section', card, keyframes, options);
- promise.then(function() {
- card.style.width = '';
+ // Allow time for the dom-ifs in settings-main to re-render.
+ // TODO(michaelpg): Use a readiness signal (e.g., from the router) rather
+ // than firing events for settings-main and running this function async.
+ this.fire('subpage-collapsing');
+ this.async(function() {
+ // Set up the close transition first to take the section out of the flow
+ // before showing everything.
+ this.closeSectionTransition_ =
+ new settings.CloseSectionTransition(section, this.scroller);
+ this.closeSectionTransition_.setUp();
+
+ this.toggleOtherSectionsHidden_(section.section, false);
+ this.classList.remove('showing-subpage');
+ this.scroller.scrollTop = this.scroller.listScrollTop_;
+
+ this.closeSectionTransition_.play()
+ .catch(function() {
+ this.fire('subpage-expand');
+ }.bind(this))
+ .then(function() {
+ this.scroller.style.overflow = '';
+ this.scroller.style.width = '';
+ this.closeSectionTransition_ = null;
+ }.bind(this));
});
- return promise;
},
};
/** @polymerBehavior */
var MainPageBehavior = [
- TransitionBehavior,
MainPageBehaviorImpl
];

Powered by Google App Engine
This is Rietveld 408576698