Chromium Code Reviews| 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..c56a1ff0896c9942773cdea9a8ff09fea2a9b9d0 |
| --- /dev/null |
| +++ b/chrome/browser/resources/settings/settings_page/open_section_transition.js |
| @@ -0,0 +1,219 @@ |
| +// 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() { |
| + 'use strict'; |
| + |
| + /** |
| + * 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']; |
|
Dan Beam
2016/07/23 01:13:44
can we make this not poke into otherObject.$.*?
e
|
| + 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; |
|
Dan Beam
2016/07/23 01:13:44
why do we need this.container? where is it used?
|
| + |
| + 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(success) { |
| + this.cleanUp_(success); |
| + return success; |
| + }.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; |
|
Dan Beam
2016/07/23 01:13:44
why do we need this.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 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(true); |
| + else |
| + this.finished = this.collapseCardTransition_.play(); |
| + |
| + this.finished.then(function(success) { |
| + if (success) |
| + unfreezeSection(this.section); |
| + else |
| + this.section.classList.add('expanded'); |
| + }.bind(this)); |
| + |
| + // Whether the animation finishes or cancels, clean up. |
| + this.finished = this.finished.then(function(success) { |
| + this.section.classList.remove('collapsing'); |
| + this.collapseCardTransition_ = null; |
| + return success; |
| + }.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, |
| + }; |
| +}); |