Index: chrome/browser/resources/settings/settings_page/open_section_transition.js |
diff --git a/chrome/browser/resources/settings/settings_page/open_section_transition.js b/chrome/browser/resources/settings/settings_page/open_section_transition.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f3b020f0ddf914120e44630e5ac5b8eea3c28d1b |
--- /dev/null |
+++ b/chrome/browser/resources/settings/settings_page/open_section_transition.js |
@@ -0,0 +1,220 @@ |
+// 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() { |
+ /** |
+ * Freezes the section's height so its card can be removed from the flow |
+ * without affecting the layout of the surrounding sections. |
+ * @param {!HTMLElement} section |
+ */ |
+ function freezeSection(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 {!HTMLElement} section |
+ */ |
+ function unfreezeSection(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 = ''; |
+ } |
+ |
+ /** |
+ * Opens a section by hiding other sections and expanding the section's card |
+ * to fill the screen vertically. |
+ * @constructor |
+ * @implements {settings.animation.AnimationGroup} |
+ * @param {!SettingsSectionElement} section |
+ * @param {!HTMLElement} container Scrolling container of sections. |
+ */ |
+ function OpenSectionTransition(section, container) { |
+ this.section = section; |
+ this.container = container; |
+ |
+ this.expandCardTransition_ = |
+ new settings.ExpandCardTransition(section.$['card'], container); |
+ } |
+ |
+ OpenSectionTransition.prototype = { |
+ __proto__: settings.animation.AnimationGroup.prototype, |
+ |
+ /** @override */ |
+ play: function() { |
+ // TODO(michaelpg): Change elevation of sections. |
+ freezeSection(this.section); |
+ this.section.classList.add('expanding'); |
+ |
+ this.expandCardTransition_.play(); |
+ |
+ this.finished = this.expandCardTransition_.finished |
+ .then(function() { |
+ this.cleanUp_(true); |
+ }.bind(this)) |
+ .catch(function(e) { |
+ this.cleanUp_(false); |
+ throw e; |
+ }.bind(this)); |
+ return this.finished; |
+ }, |
+ |
+ /** @override */ |
+ finish: function() { |
+ if (this.expandCardTransition_) |
+ this.expandCardTransition_.finish(); |
+ }, |
+ |
+ /** @override */ |
+ cancel: function() { |
+ if (this.expandCardTransition_) |
+ this.expandCardTransition_.cancel(); |
+ }, |
+ |
+ /** @override */ |
+ finished: null, |
+ |
+ /** |
+ * @param {boolean} finished Whether the animation finished. |
+ * @private |
+ */ |
+ cleanUp_: function(finished) { |
+ this.expandCardTransition_ = null; |
+ if (finished) { |
+ this.section.classList.add('expanded'); |
+ } else { |
+ // Animation was canceled; restore the section. |
+ unfreezeSection(this.section); |
+ } |
+ |
+ var card = this.section.$['card']; |
+ this.section.classList.remove('expanding'); |
+ this.section.style.height = ''; |
+ card.style.top = ''; |
+ card.style.height = ''; |
+ card.style.width = ''; |
+ }, |
+ }; |
+ |
+ /** |
+ * Closes a section by showing the other sections and collapsing the section's |
+ * card back into place. |
+ * @constructor |
+ * @implements {settings.animation.AnimationGroup} |
+ * @param {!SettingsSectionElement} section |
+ * @param {!HTMLElement} container Scrolling container of sections. |
+ */ |
+ function CloseSectionTransition(section, container) { |
+ this.section = section; |
+ this.container = container; |
+ |
+ assert(!section.classList.contains('expanding')); |
+ assert(!section.classList.contains('collapsing')); |
+ assert(section.classList.contains('expanded')); |
+ |
+ this.collapseCardTransition_ = new settings.CollapseCardTransition( |
+ section.$['card'], section.$['header'], container); |
+ } |
+ |
+ CloseSectionTransition.prototype = { |
+ __proto__: settings.animation.AnimationGroup.prototype, |
+ |
+ /** |
+ * Prepares the section for the transition by making it position: fixed. |
+ * This is useful as a separate step so the page can unhide everything |
+ * before starting the transition without this section affecting the flow. |
+ */ |
+ setUp: function() { |
+ this.collapseCardTransition_.setUp(); |
+ this.section.classList.add('collapsing'); |
+ this.section.classList.remove('expanding', 'expanded'); |
+ var card = this.section.$['card']; |
+ if (!isNaN(card.origHeight_)) { |
+ this.section.style.height = |
+ this.section.clientHeight + card.origHeight_ + 'px'; |
+ } |
+ }, |
+ |
+ /** @override */ |
+ play: function() { |
+ var card = this.section.$['card']; |
+ if (!isNaN(card.origHeight_)) |
+ this.finished = this.collapseCardTransition_.play(); |
+ |
+ // 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 as a |
+ // transition. |
+ if (isNaN(card.origHeight_)) |
+ this.finished = Promise.resolve(); |
+ |
+ this.finished.then( |
+ function() { |
+ unfreezeSection(this.section); |
+ }.bind(this), |
+ function() { |
+ this.section.classList.add('expanded'); |
+ }.bind(this)); |
+ |
+ // Whether the animation finishes or cancels, clean up. |
+ this.finished.catch(function() {}).then(function() { |
+ this.section.classList.remove('collapsing'); |
+ this.collapseCardTransition_ = null; |
+ }.bind(this)); |
+ |
+ return this.finished; |
+ }, |
+ |
+ /** @override */ |
+ finish: function() { |
+ if (this.collapseCardTransition_) |
+ this.collapseCardTransition_.finish(); |
+ }, |
+ |
+ /** @override */ |
+ cancel: function() { |
+ if (this.collapseCardTransition_) |
+ this.collapseCardTransition_.cancel(); |
+ }, |
+ |
+ /** @override */ |
+ finished: null, |
+ }; |
+ |
+ return { |
+ CloseSectionTransition: CloseSectionTransition, |
+ OpenSectionTransition: OpenSectionTransition, |
+ }; |
+}); |