Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / polymer / components-chromium / core-collapse / core-collapse-extracted.js
1
2
3   Polymer('core-collapse', {
4     /**
5      * Fired when the target element has been resized as a result of the opened
6      * state changing.
7      * 
8      * @event core-resize
9     */
10
11     /**
12      * The target element.
13      *
14      * @attribute target
15      * @type object
16      * @default null
17      */
18     target: null,
19
20     /**
21      * If true, the orientation is horizontal; otherwise is vertical.
22      *
23      * @attribute horizontal
24      * @type boolean
25      * @default false
26      */
27     horizontal: false,
28
29     /**
30      * Set opened to true to show the collapse element and to false to hide it.
31      *
32      * @attribute opened
33      * @type boolean
34      * @default false
35      */
36     opened: false,
37
38     /**
39      * Collapsing/expanding animation duration in second.
40      *
41      * @attribute duration
42      * @type number
43      * @default 0.33
44      */
45     duration: 0.33,
46
47     /**
48      * If true, the size of the target element is fixed and is set
49      * on the element.  Otherwise it will try to 
50      * use auto to determine the natural size to use
51      * for collapsing/expanding.
52      *
53      * @attribute fixedSize
54      * @type boolean
55      * @default false
56      */
57     fixedSize: false,
58
59     created: function() {
60       this.transitionEndListener = this.transitionEnd.bind(this);
61     },
62     
63     ready: function() {
64       this.target = this.target || this;
65     },
66
67     domReady: function() {
68       this.async(function() {
69         this.afterInitialUpdate = true;
70       });
71     },
72
73     detached: function() {
74       if (this.target) {
75         this.removeListeners(this.target);
76       }
77     },
78
79     targetChanged: function(old) {
80       if (old) {
81         this.removeListeners(old);
82       }
83       if (!this.target) {
84         return;
85       }
86       this.isTargetReady = !!this.target;
87       this.classList.toggle('core-collapse-closed', this.target !== this);
88       this.target.style.overflow = 'hidden';
89       this.horizontalChanged();
90       this.addListeners(this.target);
91       // set core-collapse-closed class initially to hide the target
92       this.toggleClosedClass(true);
93       this.update();
94     },
95
96     addListeners: function(node) {
97       node.addEventListener('transitionend', this.transitionEndListener);
98     },
99
100     removeListeners: function(node) {
101       node.removeEventListener('transitionend', this.transitionEndListener);
102     },
103
104     horizontalChanged: function() {
105       this.dimension = this.horizontal ? 'width' : 'height';
106     },
107
108     openedChanged: function() {
109       this.update();
110     },
111
112     /**
113      * Toggle the opened state.
114      *
115      * @method toggle
116      */
117     toggle: function() {
118       this.opened = !this.opened;
119     },
120
121     setTransitionDuration: function(duration) {
122       var s = this.target.style;
123       s.transition = duration ? (this.dimension + ' ' + duration + 's') : null;
124       if (duration === 0) {
125         this.async('transitionEnd');
126       }
127     },
128
129     transitionEnd: function() {
130       if (this.opened && !this.fixedSize) {
131         this.updateSize('auto', null);
132       }
133       this.setTransitionDuration(null);
134       this.toggleClosedClass(!this.opened);
135       this.asyncFire('core-resize', null, this.target);
136     },
137
138     toggleClosedClass: function(closed) {
139       this.hasClosedClass = closed;
140       this.target.classList.toggle('core-collapse-closed', closed);
141     },
142
143     updateSize: function(size, duration, forceEnd) {
144       this.setTransitionDuration(duration);
145       this.calcSize();
146       var s = this.target.style;
147       var nochange = s[this.dimension] === size;
148       s[this.dimension] = size;
149       // transitonEnd will not be called if the size has not changed
150       if (forceEnd && nochange) {
151         this.transitionEnd();
152       }
153     },
154
155     update: function() {
156       if (!this.target) {
157         return;
158       }
159       if (!this.isTargetReady) {
160         this.targetChanged(); 
161       }
162       this.horizontalChanged();
163       this[this.opened ? 'show' : 'hide']();
164     },
165
166     calcSize: function() {
167       return this.target.getBoundingClientRect()[this.dimension] + 'px';
168     },
169
170     getComputedSize: function() {
171       return getComputedStyle(this.target)[this.dimension];
172     },
173
174     show: function() {
175       this.toggleClosedClass(false);
176       // for initial update, skip the expanding animation to optimize
177       // performance e.g. skip calcSize
178       if (!this.afterInitialUpdate) {
179         this.transitionEnd();
180         return;
181       }
182       if (!this.fixedSize) {
183         this.updateSize('auto', null);
184         var s = this.calcSize();
185         this.updateSize(0, null);
186       }
187       this.async(function() {
188         this.updateSize(this.size || s, this.duration, true);
189       });
190     },
191
192     hide: function() {
193       // don't need to do anything if it's already hidden
194       if (this.hasClosedClass && !this.fixedSize) {
195         return;
196       }
197       if (this.fixedSize) {
198         // save the size before hiding it
199         this.size = this.getComputedSize();
200       } else {
201         this.updateSize(this.calcSize(), null);
202       }
203       this.async(function() {
204         this.updateSize(0, this.duration);
205       });
206     }
207
208   });
209