OLD | NEW |
| (Empty) |
1 <!-- Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
2 Use of this source code is governed by a BSD-style license that can be | |
3 found in the LICENSE file. --> | |
4 | |
5 <!-- | |
6 Based on <polymer-ui-collapsible>, this widget expects a child element | |
7 that has class name "cr-collapsible-header" and will expand or collapse of | |
8 the rest of the children when the header is tapped using animation. | |
9 | |
10 ex. | |
11 | |
12 <cr-collapsible active> | |
13 <div class="cr-collapsible-header"> | |
14 Tap to expand | |
15 </div> | |
16 <div>Content here</div> | |
17 <div>More content here</div> | |
18 </cr-collapsible> | |
19 | |
20 The |active| property is reflected and can be used for styling or toggled | |
21 using data binding (ex. active="{{ object.active }}") to control the | |
22 expanded state. | |
23 | |
24 TODO(esprehn): Evaluate using <core-collapse> instead. | |
25 --> | |
26 <polymer-element name="cr-collapsible" attributes="active"> | |
27 <template> | |
28 <style> | |
29 :host { | |
30 display: block; | |
31 } | |
32 #body { | |
33 height: 0; | |
34 overflow: hidden; | |
35 -webkit-transition: height 0.33s; | |
36 transition: height 0.33s; | |
37 } | |
38 </style> | |
39 <div on-tap="{{ handleHeaderTap }}"> | |
40 <content select=".cr-collapsible-header"></content> | |
41 </div> | |
42 <div id="body" | |
43 on-webkitTransitionEnd="{{ handleTransitionEnd }}" | |
44 on-transitionEnd="{{ handleTransitionEnd }}"> | |
45 <content></content> | |
46 </div> | |
47 </template> | |
48 <script> | |
49 Polymer("cr-collapsible", { | |
50 publish: { | |
51 active: {value: false, reflect: true}, | |
52 }, | |
53 created: function() { | |
54 this.active = false; | |
55 this.afterInitialUpdate = false; | |
56 }, | |
57 attached: function() { | |
58 this.$.body.hidden = !this.active; | |
59 this.$.body.style.height = "auto"; | |
60 this.async(function() { | |
61 this.afterInitialUpdate = true; | |
62 }); | |
63 }, | |
64 activeChanged: function() { | |
65 this.update(); | |
66 }, | |
67 toggle: function() { | |
68 this.active = !this.active; | |
69 }, | |
70 handleHeaderTap: function() { | |
71 this.toggle(); | |
72 }, | |
73 handleTransitionEnd: function() { | |
74 if (this.active) | |
75 this.updateSize("auto"); | |
76 this.$.body.hidden = !this.active; | |
77 }, | |
78 updateSize: function(size, didTransition) { | |
79 var bodyStyle = this.$.body.style; | |
80 // Transition events don't fire if the property doesn't change | |
81 // so we need to manually call the handler. | |
82 if (didTransition && bodyStyle.height === size) | |
83 this.handleTransitionEnd(); | |
84 else | |
85 bodyStyle.height = size; | |
86 }, | |
87 update: function() { | |
88 this[this.active ? "show" : "hide"](); | |
89 }, | |
90 computeBodySize: function() { | |
91 return this.$.body.getBoundingClientRect().height + "px"; | |
92 }, | |
93 show: function() { | |
94 this.$.body.hidden = false; | |
95 | |
96 // Don't play the animation until after the initial update to | |
97 // avoid having all collapsibles animate open on view load. | |
98 if (!this.afterInitialUpdate) | |
99 return; | |
100 | |
101 this.updateSize("auto"); | |
102 var size = this.computeBodySize(); | |
103 this.updateSize("0"); | |
104 | |
105 this.async(function() { | |
106 this.computeBodySize(); | |
107 this.updateSize(size, true); | |
108 }); | |
109 }, | |
110 hide: function() { | |
111 if (this.$.body.hidden) | |
112 return; | |
113 this.updateSize(this.computeBodySize()); | |
114 this.async(function() { | |
115 this.computeBodySize(); | |
116 this.updateSize("0", true); | |
117 }); | |
118 }, | |
119 }); | |
120 </script> | |
121 </polymer-element> | |
OLD | NEW |