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