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 |