| 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 * | 9 * |
| 10 * Example: | 10 * Example: |
| 11 * | 11 * |
| 12 * <settings-section page-title="[[pageTitle]]" section="privacy"> | 12 * <settings-section page-title="[[pageTitle]]" section="privacy"> |
| 13 * <!-- Insert your section controls here --> | 13 * <!-- Insert your section controls here --> |
| 14 * </settings-section> | 14 * </settings-section> |
| 15 * | 15 * |
| 16 * @group Chrome Settings Elements | 16 * @group Chrome Settings Elements |
| 17 * @element settings-section | 17 * @element settings-section |
| 18 */ | 18 */ |
| 19 Polymer({ | 19 Polymer({ |
| 20 is: 'settings-section', | 20 is: 'settings-section', |
| 21 | 21 |
| 22 behaviors: [ | |
| 23 Polymer.NeonAnimationRunnerBehavior, | |
| 24 ], | |
| 25 | |
| 26 properties: { | 22 properties: { |
| 27 /** | 23 /** |
| 28 * The current active route. | 24 * The current active route. |
| 29 */ | 25 */ |
| 30 currentRoute: { | 26 currentRoute: Object, |
| 31 type: Object, | |
| 32 observer: 'currentRouteChanged_', | |
| 33 }, | |
| 34 | 27 |
| 35 /** | 28 /** |
| 36 * The section is expanded to a full-page view when this property matches | 29 * The section is expanded to a full-page view when this property matches |
| 37 * currentRoute.section. | 30 * currentRoute.section. |
| 38 * | 31 * |
| 39 * The section name must match the name specified in settings_router.js. | 32 * The section name must match the name specified in settings_router.js. |
| 40 */ | 33 */ |
| 41 section: { | 34 section: { |
| 42 type: String, | 35 type: String, |
| 43 }, | 36 }, |
| 44 | 37 |
| 45 /** | 38 /** |
| 46 * Title for the page header and navigation menu. | 39 * Title for the page header and navigation menu. |
| 47 */ | 40 */ |
| 48 pageTitle: String, | 41 pageTitle: String, |
| 49 | |
| 50 animationConfig: { | |
| 51 value: function() { | |
| 52 return { | |
| 53 collapse: { | |
| 54 name: 'collapse-card-animation', | |
| 55 node: this, | |
| 56 }, | |
| 57 expand: { | |
| 58 name: 'expand-card-animation', | |
| 59 node: this, | |
| 60 }, | |
| 61 }; | |
| 62 }, | |
| 63 }, | |
| 64 }, | |
| 65 | |
| 66 listeners: { | |
| 67 'expand-animation-complete': 'onExpandAnimationComplete_', | |
| 68 }, | |
| 69 | |
| 70 /** @private */ | |
| 71 currentRouteChanged_: function(newRoute, oldRoute) { | |
| 72 var newExpanded = newRoute.section == this.section; | |
| 73 var oldExpanded = oldRoute && oldRoute.section == this.section; | |
| 74 | |
| 75 var visible = newExpanded || this.currentRoute.section == ''; | |
| 76 | |
| 77 // If the user navigates directly to a subpage, skip all the animations. | |
| 78 if (!oldRoute) { | |
| 79 if (newExpanded) { | |
| 80 // If we navigate directly to a subpage, skip animations. | |
| 81 this.classList.add('expanded'); | |
| 82 } else if (!visible) { | |
| 83 this.hidden = true; | |
| 84 this.$.card.elevation = 0; | |
| 85 } | |
| 86 | |
| 87 return; | |
| 88 } | |
| 89 | |
| 90 if (newExpanded && !oldExpanded) { | |
| 91 this.playAnimation('expand'); | |
| 92 } else if (oldExpanded && !newExpanded) { | |
| 93 // For contraction, we defer the animation to allow | |
| 94 // settings-animated-pages to reflow the new page correctly. | |
| 95 this.async(function() { | |
| 96 this.playAnimation('collapse'); | |
| 97 }.bind(this)); | |
| 98 } | |
| 99 | |
| 100 this.$.card.elevation = visible ? 1 : 0; | |
| 101 | |
| 102 // Remove 'hidden' class immediately, but defer adding it if we are invisble | |
| 103 // until the animation is complete. | |
| 104 if (visible) | |
| 105 this.hidden = false; | |
| 106 }, | |
| 107 | |
| 108 /** @private */ | |
| 109 onExpandAnimationComplete_: function() { | |
| 110 this.hidden = this.currentRoute.section != '' && | |
| 111 this.currentRoute.section != this.section; | |
| 112 }, | 42 }, |
| 113 }); | 43 }); |
| 114 | |
| 115 Polymer({ | |
| 116 is: 'expand-card-animation', | |
| 117 | |
| 118 behaviors: [ | |
| 119 Polymer.NeonAnimationBehavior | |
| 120 ], | |
| 121 | |
| 122 configure: function(config) { | |
| 123 var section = config.node; | |
| 124 var card = section.$.card; | |
| 125 var containerRect = section.offsetParent.getBoundingClientRect(); | |
| 126 var cardRect = card.getBoundingClientRect(); | |
| 127 | |
| 128 // Set placeholder height so the page does not reflow during animation. | |
| 129 // TODO(tommycli): For URLs that directly load subpages, this does not work. | |
| 130 var placeholder = section.$.placeholder; | |
| 131 placeholder.style.top = card.offsetTop + 'px'; | |
| 132 placeholder.style.height = card.offsetHeight + 'px'; | |
| 133 | |
| 134 section.classList.add('neon-animating'); | |
| 135 | |
| 136 this._effect = new KeyframeEffect(card, [ | |
| 137 {'top': cardRect.top + 'px', 'height': cardRect.height + 'px'}, | |
| 138 {'top': containerRect.top + 'px', 'height': containerRect.height + 'px'}, | |
| 139 ], this.timingFromConfig(config)); | |
| 140 return this._effect; | |
| 141 }, | |
| 142 | |
| 143 complete: function(config) { | |
| 144 var section = config.node; | |
| 145 section.classList.remove('neon-animating'); | |
| 146 section.classList.add('expanded'); | |
| 147 | |
| 148 // This event fires on itself as well, but that is benign. | |
| 149 var sections = section.parentNode.querySelectorAll('settings-section'); | |
| 150 for (var i = 0; i < sections.length; ++i) { | |
| 151 sections[i].fire('expand-animation-complete'); | |
| 152 } | |
| 153 } | |
| 154 }); | |
| 155 | |
| 156 Polymer({ | |
| 157 is: 'collapse-card-animation', | |
| 158 | |
| 159 behaviors: [ | |
| 160 Polymer.NeonAnimationBehavior | |
| 161 ], | |
| 162 | |
| 163 configure: function(config) { | |
| 164 var section = config.node; | |
| 165 var oldRect = section.offsetParent.getBoundingClientRect(); | |
| 166 | |
| 167 section.classList.remove('expanded'); | |
| 168 | |
| 169 var card = section.$.card; | |
| 170 var placeholder = section.$.placeholder; | |
| 171 placeholder.style.top = card.offsetTop + 'px'; | |
| 172 placeholder.style.height = card.offsetHeight + 'px'; | |
| 173 | |
| 174 var newRect = card.getBoundingClientRect(); | |
| 175 | |
| 176 section.classList.add('neon-animating'); | |
| 177 | |
| 178 this._effect = new KeyframeEffect(card, [ | |
| 179 {'top': oldRect.top + 'px', 'height': oldRect.height + 'px'}, | |
| 180 {'top': newRect.top + 'px', 'height': newRect.height + 'px'}, | |
| 181 ], this.timingFromConfig(config)); | |
| 182 return this._effect; | |
| 183 }, | |
| 184 | |
| 185 complete: function(config) { | |
| 186 config.node.classList.remove('neon-animating'); | |
| 187 } | |
| 188 }); | |
| OLD | NEW |