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

Unified Diff: chrome/browser/resources/settings/settings_page/settings_section.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: Refactor Created 4 years, 4 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/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 1149e2ea81b7aa0fd017246548977f7e8916be2b..d19ba410b62c21263d72da89146e80a6ae513aed 100644
--- a/chrome/browser/resources/settings/settings_page/settings_section.js
+++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -6,6 +6,8 @@
* @fileoverview
* 'settings-section' shows a paper material themed section with a header
* which shows its page title.
+
dschuyler 2016/08/04 18:36:51 Maybe remove blank line or add an '*'?
+ * The section can expand vertically to to its container's padding edge.
*
* Example:
*
@@ -23,18 +25,184 @@ Polymer({
currentRoute: Object,
/**
- * The section is expanded to a full-page view when this property matches
+ * The section name should match a name specified in route.js. The
+ * MainPageBehavior will expand this section if this section name matches
* currentRoute.section.
- *
- * The section name must match the name specified in settings_router.js.
*/
- section: {
- type: String,
- },
+ section: String,
+
+ /** Title for the section header. */
+ pageTitle: String,
/**
- * Title for the page header and navigation menu.
+ * 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
*/
- pageTitle: String,
+ collapsedHeight_: {
+ type: Number,
+ value: NaN,
+ },
+ },
+
+ /**
+ * @return {boolean} True if the section is currently rendered and not
+ * already expanded or transitioning.
+ */
+ canAnimateExpand: function() {
+ 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, 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.
+ *
+ * The animation does not "last", so the parent must properly position it
+ * afterwards in its container.
+ *
+ * @param {!HTMLElement} container The scrolling container to fill.
+ * @return {!settings.animation.Animation}
+ */
+ animateExpand: function(container) {
+ // 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');
+
+ // 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';
+
+ // 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);
+
+ // Whether the animation fails or succeeds, clean up the properties we set.
+ animation.finished.catch(function() {}).then(function() {
+ this.classList.remove('expanding');
+ this.style.height = '';
+ }.bind(this));
+ return animation;
+ },
+
+ /** @return {boolean} True if the section is currently expanded. */
+ canAnimateCollapse: function() {
+ 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().
+ */
+ 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.add('collapsing');
+ this.style.height = this.collapsedHeight_ + 'px';
+ },
+
+ /**
+ * Collapses an expanded section's card back into position in the main page.
+ * Call after calling animateCollapse(), unhiding other content and scrolling.
+ * @param {!HTMLElement} container The scrolling container the card fills.
+ * @return {!settings.animation.Animation}
+ */
+ 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);
+
+ // Start the card at its current height and distance from our top.
+ var startTop = distance + 'px';
+ var startHeight = this.$.card.style.height;
+
+ // End at the bottom of our header.
+ var endTop = cardTargetTop + 'px';
+ var endHeight = (this.collapsedHeight_ - cardTargetTop) + 'px';
+
+ // The card no longer needs position: fixed.
+ this.$.card.style.position = '';
+
+ // 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 = '';
+
+ // Whether the animation fails or succeeds, clean up the properties we set.
+ animation.finished.catch(function() {}).then(function() {
+ // The card now determines the section's height automatically.
+ this.style.height = '';
+ this.classList.remove('collapsing');
+ }.bind(this));
+ return animation;
+ },
+
+ /**
+ * 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,
+ };
+
+ var options = /** @type {!KeyframeEffectOptions} */({
+ duration: settings.animation.Timing.DURATION,
+ easing: settings.animation.Timing.EASING,
+ });
+
+ return new settings.animation.Animation(
+ this.$.card, [startFrame, endFrame], options);
},
});

Powered by Google App Engine
This is Rietveld 408576698