Index: chrome/browser/resources/settings/settings_page/expand_card_transition.js |
diff --git a/chrome/browser/resources/settings/settings_page/expand_card_transition.js b/chrome/browser/resources/settings/settings_page/expand_card_transition.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..97a0ed51c2b6fef803cbe26c164f8cfc81651627 |
--- /dev/null |
+++ b/chrome/browser/resources/settings/settings_page/expand_card_transition.js |
@@ -0,0 +1,186 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+cr.define('settings', function() { |
+ /** |
+ * Expands a card to fill its container's client height, so it covers the |
+ * container from the top padding edge to the bottom padding edge. |
+ * @see https://www.w3.org/TR/cssom-view-1/#terminology |
+ * @constructor |
+ * @implements {settings.animation.AnimationGroup} |
+ * @param {!HTMLElement} card Card to expand. |
+ * @param {!HTMLElement} container Container whose height the card will span. |
+ */ |
+ function ExpandCardTransition(card, container) { |
+ /** @private */ |
+ this.card_ = card; |
+ /** @private */ |
+ this.container_ = container; |
+ } |
+ |
+ ExpandCardTransition.prototype = { |
+ __proto__: settings.animation.AnimationGroup.prototype, |
+ |
+ /** @override */ |
+ play: function() { |
+ // If we're running this transition before anything else, we won't have |
+ // the information we need, so just expand immediately and finish. |
+ if (typeof this.card_.origHeight_ == 'undefined' || |
+ this.card_.style.top == '' || this.card_.style.height == '') { |
+ this.finished = Promise.resolve(); |
+ return this.finished; |
+ } |
+ |
+ // Align the card with the container's padding edge. |
+ var startingTop = this.card_.getBoundingClientRect().top; |
+ |
+ // Target position is the container's top edge in the viewport. |
+ var targetTop = this.container_.getBoundingClientRect().top; |
+ |
+ // The target height shouldn't use the container's current height, because |
+ // the container may resize when the window resizes. And height: 100% |
+ // wouldn't use the container's height because we're position: fixed. |
+ // |
+ // Instead, find the part of the window height *not* used by the container |
+ // (e.g., for a toolbar) and calc the height dynamically. This assumes the |
+ // excluded height stays constant. |
+ var excludedHeight = window.innerHeight - this.container_.clientHeight; |
+ var targetHeight = 'calc(100% - ' + excludedHeight + 'px)'; |
+ |
+ // Expand the card. The card's height must be 100% of the container's |
+ // height or taller, so we use minHeight rather than height. |
+ var keyframes = [{ |
+ top: startingTop + 'px', |
+ minHeight: this.card_.style.height, |
+ easing: settings.animation.Timing.EASING, |
+ }, { |
+ top: targetTop + 'px', |
+ minHeight: 'calc(100% - ' + targetTop + 'px)', |
+ }]; |
+ var options = /** @type {!KeyframeEffectOptions} */({ |
+ duration: settings.animation.Timing.DURATION, |
+ }); |
+ |
+ /** @type {?settings.animation.Animation} */ |
+ this.animation_ = |
+ new settings.animation.Animation(this.card_, keyframes, options); |
+ this.finished = this.animation_.finished; |
+ return this.finished; |
+ }, |
+ |
+ /** @override */ |
+ finish: function() { |
+ if (!this.animation_) |
+ return; |
+ this.animation_.finish(); |
+ this.animation_ = null; |
+ }, |
+ |
+ /** @override */ |
+ cancel: function() { |
+ if (!this.animation_) |
+ return; |
+ this.animation_.cancel(); |
+ this.animation_ = null; |
+ }, |
+ |
+ /** @override */ |
+ finished: null, |
+ }; |
+ |
+ /** |
+ * Collapses an expanded card back into its original section. |
+ * @constructor |
+ * @implements {settings.animation.AnimationGroup} |
+ * @param {!HTMLElement} card Card to collapse. |
+ * @param {!HTMLElement} header Header for the section. |
+ * @param {!HTMLElement} container Container the card currently spans. |
+ */ |
+ function CollapseCardTransition(card, header, container) { |
+ /** @private */ |
+ this.card_ = card; |
+ /** @private */ |
+ this.header_ = header; |
+ /** @private */ |
+ this.container_ = container; |
+ } |
+ |
+ CollapseCardTransition.prototype = { |
+ __proto__: settings.animation.AnimationGroup.prototype, |
+ |
+ /** |
+ * Prepare for the transition before other page content has been unhidden. |
michaelpg
2016/07/20 22:10:57
"Prepares"
|
+ * Call before play(). |
+ */ |
+ setUp: function() { |
+ this.card_.style.width = this.card_.clientWidth + 'px'; |
+ this.card_.style.height = this.card_.clientHeight + 'px'; |
+ }, |
+ |
+ /** @override */ |
+ play: function() { |
+ var startingTop = this.container_.getBoundingClientRect().top; |
+ |
+ // The card is unpositioned, so use its position as the ending state, |
+ // but account for scroll. |
+ var targetTop = this.card_.getBoundingClientRect().top - |
+ this.container_.scrollTop; |
+ |
+ // Account for the section header. |
+ var headerStyle = getComputedStyle(this.header_); |
+ targetTop += this.header_.offsetHeight + |
+ parseFloat(headerStyle.marginBottom) + |
+ parseFloat(headerStyle.marginTop); |
+ |
+ var keyframes = [{ |
+ top: startingTop + 'px', |
+ minHeight: this.card_.style.height, |
+ easing: settings.animation.Timing.EASING, |
+ }, { |
+ top: targetTop + 'px', |
+ minHeight: |
+ /** @type {{origHeight_: number}} */(this.card_).origHeight_ + 'px', |
+ }]; |
+ var options = /** @type {!KeyframeEffectOptions} */({ |
+ duration: settings.animation.Timing.DURATION, |
+ }); |
+ |
+ this.card_.style.height = ''; |
+ |
+ /** @type {?settings.animation.Animation} */ |
+ this.animation_ = |
+ new settings.animation.Animation(this.card_, keyframes, options); |
+ this.finished = this.animation_.finished; |
+ // Clean up after the animation finishes or cancels. |
+ this.finished.catch(function() {}).then(function() { |
+ this.card_.style.width = ''; |
+ }.bind(this)); |
+ return this.finished; |
+ }, |
+ |
+ /** @override */ |
+ finish: function() { |
+ if (!this.animation_) |
+ return; |
+ this.animation_.finish(); |
+ this.animation_ = null; |
+ }, |
+ |
+ /** @override */ |
+ cancel: function() { |
+ if (!this.animation_) |
+ return; |
+ this.animation_.cancel(); |
+ this.animation_ = null; |
+ }, |
+ |
+ /** @override */ |
+ finished: null, |
+ }; |
+ |
+ return { |
+ CollapseCardTransition: CollapseCardTransition, |
+ ExpandCardTransition: ExpandCardTransition, |
+ }; |
+}); |