3 Polymer('core-collapse', {
6 * Fired when the `core-collapse`'s `opened` property changes.
8 * @event core-collapse-open
12 * Fired when the target element has been resized as a result of the opened
19 * The target element that will be opened when the `core-collapse` is
20 * opened. If unspecified, the `core-collapse` itself is the target.
29 * If true, the orientation is horizontal; otherwise is vertical.
31 * @attribute horizontal
38 * Set opened to true to show the collapse element and to false to hide it.
47 * Collapsing/expanding animation duration in second.
56 * If true, the size of the target element is fixed and is set
57 * on the element. Otherwise it will try to
58 * use auto to determine the natural size to use
59 * for collapsing/expanding.
61 * @attribute fixedSize
68 * By default the collapsible element is set to overflow hidden. This helps
69 * avoid element bleeding outside the region and provides consistent overflow
70 * style across opened and closed states. Set this property to true to allow
71 * the collapsible element to overflow when it's opened.
73 * @attribute allowOverflow
80 this.transitionEndListener = this.transitionEnd.bind(this);
84 this.target = this.target || this;
87 domReady: function() {
88 this.async(function() {
89 this.afterInitialUpdate = true;
93 detached: function() {
95 this.removeListeners(this.target);
99 targetChanged: function(old) {
101 this.removeListeners(old);
106 this.isTargetReady = !!this.target;
107 this.classList.toggle('core-collapse-closed', this.target !== this);
108 this.toggleOpenedStyle(false);
109 this.horizontalChanged();
110 this.addListeners(this.target);
111 // set core-collapse-closed class initially to hide the target
112 this.toggleClosedClass(true);
116 addListeners: function(node) {
117 node.addEventListener('transitionend', this.transitionEndListener);
120 removeListeners: function(node) {
121 node.removeEventListener('transitionend', this.transitionEndListener);
124 horizontalChanged: function() {
125 this.dimension = this.horizontal ? 'width' : 'height';
128 openedChanged: function() {
130 this.fire('core-collapse-open', this.opened);
134 * Toggle the opened state.
139 this.opened = !this.opened;
142 setTransitionDuration: function(duration) {
143 var s = this.target.style;
144 s.transition = duration ? (this.dimension + ' ' + duration + 's') : null;
145 if (duration === 0) {
146 this.async('transitionEnd');
150 transitionEnd: function() {
151 if (this.opened && !this.fixedSize) {
152 this.updateSize('auto', null);
154 this.setTransitionDuration(null);
155 this.toggleOpenedStyle(this.opened);
156 this.toggleClosedClass(!this.opened);
157 this.asyncFire('core-resize', null, this.target);
160 toggleClosedClass: function(closed) {
161 this.hasClosedClass = closed;
162 this.target.classList.toggle('core-collapse-closed', closed);
165 toggleOpenedStyle: function(opened) {
166 this.target.style.overflow = this.allowOverflow && opened ? '' : 'hidden';
169 updateSize: function(size, duration, forceEnd) {
170 this.setTransitionDuration(duration);
172 var s = this.target.style;
173 var nochange = s[this.dimension] === size;
174 s[this.dimension] = size;
175 // transitonEnd will not be called if the size has not changed
176 if (forceEnd && nochange) {
177 this.transitionEnd();
185 if (!this.isTargetReady) {
186 this.targetChanged();
188 this.horizontalChanged();
189 this[this.opened ? 'show' : 'hide']();
192 calcSize: function() {
193 return this.target.getBoundingClientRect()[this.dimension] + 'px';
196 getComputedSize: function() {
197 return getComputedStyle(this.target)[this.dimension];
201 this.toggleClosedClass(false);
202 // for initial update, skip the expanding animation to optimize
203 // performance e.g. skip calcSize
204 if (!this.afterInitialUpdate) {
205 this.transitionEnd();
208 if (!this.fixedSize) {
209 this.updateSize('auto', null);
210 var s = this.calcSize();
212 this.transitionEnd();
215 this.updateSize(0, null);
217 this.async(function() {
218 this.updateSize(this.size || s, this.duration, true);
223 this.toggleOpenedStyle(false);
224 // don't need to do anything if it's already hidden
225 if (this.hasClosedClass && !this.fixedSize) {
228 if (this.fixedSize) {
229 // save the size before hiding it
230 this.size = this.getComputedSize();
232 this.updateSize(this.calcSize(), null);
234 this.async(function() {
235 this.updateSize(0, this.duration);