Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * 'settings-section' shows a paper material themed section with a header | 7 * 'settings-section' shows a paper material themed section with a header |
| 8 * which shows its page title. | 8 * which shows its page title. |
| 9 | |
|
Dan Beam
2016/08/05 04:14:38
*
michaelpg
2016/08/05 05:16:08
Done.
| |
| 10 * The section can expand vertically to fill its container's padding edge. | |
| 9 * | 11 * |
| 10 * Example: | 12 * Example: |
| 11 * | 13 * |
| 12 * <settings-section page-title="[[pageTitle]]" section="privacy"> | 14 * <settings-section page-title="[[pageTitle]]" section="privacy"> |
| 13 * <!-- Insert your section controls here --> | 15 * <!-- Insert your section controls here --> |
| 14 * </settings-section> | 16 * </settings-section> |
| 15 */ | 17 */ |
| 16 Polymer({ | 18 |
| 19 // Fast out, slow in. | |
| 20 var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)'; | |
| 21 var EXPAND_DURATION = 350; | |
| 22 | |
| 23 var SettingsSectionElement = Polymer({ | |
| 17 is: 'settings-section', | 24 is: 'settings-section', |
| 18 | 25 |
| 19 properties: { | 26 properties: { |
| 20 /** | 27 /** |
| 21 * The current active route. | 28 * The current active route. |
| 22 */ | 29 */ |
| 23 currentRoute: Object, | 30 currentRoute: Object, |
| 24 | 31 |
| 25 /** | 32 /** |
| 26 * The section is expanded to a full-page view when this property matches | 33 * The section name should match a name specified in route.js. The |
| 34 * MainPageBehavior will expand this section if this section name matches | |
| 27 * currentRoute.section. | 35 * currentRoute.section. |
| 28 * | |
| 29 * The section name must match the name specified in settings_router.js. | |
| 30 */ | 36 */ |
| 31 section: { | 37 section: String, |
| 32 type: String, | 38 |
| 33 }, | 39 /** Title for the section header. */ |
| 34 | |
| 35 /** | |
| 36 * Title for the page header and navigation menu. | |
| 37 */ | |
| 38 pageTitle: String, | 40 pageTitle: String, |
| 39 }, | 41 }, |
| 42 | |
| 43 /** | |
| 44 * Freezes the section's height so its card can be removed from the flow | |
| 45 * without affecting the layout of the surrounding sections. | |
| 46 * @private | |
| 47 */ | |
| 48 freezeDimensions: function() { | |
|
michaelpg
2016/08/05 02:09:11
The contents of the following functions were moved
Dan Beam
2016/08/05 04:14:38
does this need a
if (this.classList.contains('fro
michaelpg
2016/08/05 05:16:08
Probably? I'm reluctant to make changes like that.
| |
| 49 var card = this.$.card; | |
| 50 this.style.height = this.clientHeight + 'px'; | |
| 51 | |
| 52 var cardHeight = card.offsetHeight; | |
| 53 var cardWidth = card.offsetWidth; | |
| 54 // If the section is not displayed yet (e.g., navigated directly to a | |
| 55 // sub-page), cardHeight and cardWidth are 0, so do not set the height or | |
| 56 // width explicitly. | |
| 57 // TODO(michaelpg): Improve this logic when refactoring | |
| 58 // settings-animated-pages. | |
| 59 if (cardHeight && cardWidth) { | |
| 60 // TODO(michaelpg): Temporary hack to store the height the section should | |
| 61 // collapse to when it closes. | |
| 62 card.origHeight_ = cardHeight; | |
|
michaelpg
2016/08/05 02:09:11
I could take care of this TODO now with a property
Dan Beam
2016/08/05 04:14:38
Acknowledged.
| |
| 63 | |
| 64 card.style.height = cardHeight + 'px'; | |
| 65 card.style.width = cardWidth + 'px'; | |
| 66 } else { | |
| 67 // Set an invalid value so we don't try to use it later. | |
| 68 card.origHeight_ = NaN; | |
| 69 } | |
| 70 | |
| 71 // Place the section's card at its current position but removed from the | |
| 72 // flow. | |
| 73 card.style.top = card.getBoundingClientRect().top + 'px'; | |
| 74 this.classList.add('frozen'); | |
| 75 }, | |
| 76 | |
| 77 /** After freezeDimensions, restores the section to its normal height. */ | |
| 78 unfreezeDimensions: function() { | |
| 79 if (!this.classList.contains('frozen')) | |
| 80 return; | |
| 81 this.classList.remove('frozen'); | |
| 82 this.$.card.style.top = ''; | |
| 83 this.$.card.style.height = ''; | |
| 84 this.$.card.style.width = ''; | |
| 85 this.style.height = ''; | |
| 86 }, | |
| 87 | |
| 88 /** | |
| 89 * @return {boolean} True if the section is currently rendered and not | |
| 90 * already expanded or transitioning. | |
| 91 */ | |
| 92 canAnimateExpand: function() { | |
| 93 return !this.classList.contains('expanded'); | |
| 94 }, | |
| 95 | |
| 96 /** | |
| 97 * Animates the section expanding to fill the container. The section is fixed | |
| 98 * in the viewport during the animation. The section adds the "expanding" | |
| 99 * class while the animation plays. | |
| 100 * | |
| 101 * @param {!HTMLElement} container The scrolling container to fill. | |
| 102 * @return {?SettingsSectionElement.AnimationConfig} | |
| 103 */ | |
| 104 animateExpand: function(container) { | |
| 105 var card = this.$.card; | |
| 106 | |
| 107 // The card should start at the top of the page. | |
| 108 var targetTop = container.getBoundingClientRect().top; | |
| 109 | |
| 110 this.classList.add('expanding'); | |
| 111 | |
| 112 // Nothing to animate. | |
| 113 if (!card.style.top || !card.style.height) | |
| 114 return null; | |
| 115 | |
| 116 // Expand the card, using minHeight. (The card must span the container's | |
| 117 // client height, so it must be at least 100% in case the card is too short. | |
| 118 // If the card is already taller than the container's client height, we | |
| 119 // don't want to shrink the card to 100% or the content will overflow, so | |
| 120 // we can't use height, and animating height wouldn't look right anyway.) | |
| 121 var keyframes = [{ | |
| 122 top: card.style.top, | |
| 123 minHeight: card.style.height, | |
| 124 easing: EASING_FUNCTION, | |
| 125 }, { | |
| 126 top: targetTop + 'px', | |
| 127 minHeight: 'calc(100% - ' + targetTop + 'px)', | |
| 128 }]; | |
| 129 var options = /** @type {!KeyframeEffectOptions} */({ | |
| 130 duration: EXPAND_DURATION | |
| 131 }); | |
| 132 // TODO(michaelpg): Change elevation of sections. | |
| 133 return {card: card, keyframes: keyframes, options: options}; | |
| 134 }, | |
| 135 | |
| 136 /** | |
| 137 * Cleans up after animateExpand(). | |
| 138 * @param {boolean} finished Whether the animation finished successfully. | |
| 139 */ | |
| 140 cleanUpAnimateExpand: function(finished) { | |
| 141 if (finished) { | |
| 142 this.classList.add('expanded'); | |
| 143 this.$.card.style.top = ''; | |
| 144 this.$.header.hidden = true; | |
| 145 this.style.height = ''; | |
| 146 } | |
| 147 | |
| 148 this.classList.remove('expanding'); | |
| 149 this.$.card.style.height = ''; | |
| 150 this.$.card.style.width = ''; | |
| 151 }, | |
| 152 | |
| 153 /** @return {boolean} True if the section is currently expanded. */ | |
| 154 canAnimateCollapse: function() { | |
| 155 return this.classList.contains('expanded'); | |
| 156 }, | |
| 157 | |
| 158 /** | |
| 159 * Collapses an expanded section's card back into position in the main page. | |
| 160 * Adds the "expanding" class during the animation. | |
| 161 * @param {!HTMLElement} container The scrolling container the card fills. | |
| 162 * @param {number} prevScrollTop scrollTop of the container before this | |
| 163 * section expanded. | |
| 164 * @return {?SettingsSectionElement.AnimationConfig} | |
| 165 */ | |
| 166 animateCollapse: function(container, prevScrollTop) { | |
|
Dan Beam
2016/08/05 04:14:38
both animateCollapse and animateExpand are weird t
michaelpg
2016/08/05 05:16:08
Acknowledged. I'll work on that in a followup CL.
| |
| 167 this.$.header.hidden = false; | |
| 168 | |
| 169 var startingTop = container.getBoundingClientRect().top; | |
| 170 | |
| 171 var card = this.$.card; | |
| 172 var cardHeightStart = card.clientHeight; | |
| 173 var cardWidthStart = card.clientWidth; | |
| 174 | |
| 175 this.classList.add('collapsing'); | |
| 176 this.classList.remove('expanding', 'expanded'); | |
| 177 | |
| 178 // If we navigated here directly, we don't know the original height of the | |
| 179 // section, so we skip the animation. | |
| 180 // TODO(michaelpg): remove this condition once sliding is implemented. | |
| 181 if (isNaN(card.origHeight_)) | |
|
Dan Beam
2016/08/05 04:14:38
nit: use isNaN or Number.isNan() consistently (I v
michaelpg
2016/08/05 05:16:08
Done (cut and pasted code)
I prefer Number.isNaN
| |
| 182 return null; | |
| 183 | |
| 184 // Restore the section to its proper height to make room for the card. | |
| 185 this.style.height = this.clientHeight + card.origHeight_ + 'px'; | |
|
Dan Beam
2016/08/05 04:14:38
nit: use parens with differently typed args that e
michaelpg
2016/08/05 05:16:08
Done (cut and pasted code)
| |
| 186 | |
| 187 // TODO(michaelpg): this should be in MainPageBehavior(), but we need to | |
| 188 // wait until the full page height is available (setting the section | |
| 189 // height). | |
| 190 container.scrollTop = prevScrollTop; | |
| 191 | |
| 192 // The card is unpositioned, so use its position as the ending state, | |
| 193 // but account for scroll. | |
| 194 var targetTop = card.getBoundingClientRect().top - container.scrollTop; | |
| 195 | |
| 196 // Account for the section header. | |
| 197 var headerStyle = getComputedStyle(this.$.header); | |
| 198 targetTop += this.$.header.offsetHeight + | |
| 199 parseInt(headerStyle.marginBottom, 10) + | |
| 200 parseInt(headerStyle.marginTop, 10); | |
| 201 | |
| 202 var keyframes = [{ | |
| 203 top: startingTop + 'px', | |
| 204 minHeight: cardHeightStart + 'px', | |
| 205 easing: EASING_FUNCTION, | |
| 206 }, { | |
| 207 top: targetTop + 'px', | |
| 208 minHeight: card.origHeight_ + 'px', | |
| 209 }]; | |
| 210 var options = /** @type {!KeyframeEffectOptions} */({ | |
| 211 duration: EXPAND_DURATION | |
| 212 }); | |
| 213 | |
| 214 card.style.width = cardWidthStart + 'px'; | |
| 215 | |
| 216 return {card: card, keyframes: keyframes, options: options}; | |
| 217 }, | |
| 218 | |
| 219 /** | |
| 220 * Cleans up after animateCollapse(). | |
| 221 * @param {boolean} finished Whether the animation finished successfully. | |
| 222 */ | |
| 223 cleanUpAnimateCollapse: function(finished) { | |
| 224 if (finished) | |
| 225 this.$.card.style.width = ''; | |
| 226 }, | |
| 40 }); | 227 }); |
| 228 | |
| 229 /** | |
| 230 * Information needed by TransitionBehavior to schedule animations. | |
| 231 * @typedef {{ | |
|
michaelpg
2016/08/05 02:09:11
This typedef is temporary, the animations will eve
Dan Beam
2016/08/05 04:14:38
Acknowledged.
| |
| 232 * card: !HTMLElement, | |
| 233 * keyframes: !Array<!Object>, | |
| 234 * options: !KeyframeEffectOptions | |
| 235 * }} | |
| 236 */ | |
| 237 SettingsSectionElement.AnimationConfig; | |
| OLD | NEW |