|
1 /* |
|
2 YUI 3.10.3 (build 2fb5187) |
|
3 Copyright 2013 Yahoo! Inc. All rights reserved. |
|
4 Licensed under the BSD License. |
|
5 http://yuilibrary.com/license/ |
|
6 */ |
|
7 |
|
8 YUI.add('transition-timer', function (Y, NAME) { |
|
9 |
|
10 /** |
|
11 * Provides the base Transition class, for animating numeric properties. |
|
12 * |
|
13 * @module transition |
|
14 * @submodule transition-timer |
|
15 */ |
|
16 |
|
17 |
|
18 var Transition = Y.Transition; |
|
19 |
|
20 Y.mix(Transition.prototype, { |
|
21 _start: function() { |
|
22 if (Transition.useNative) { |
|
23 this._runNative(); |
|
24 } else { |
|
25 this._runTimer(); |
|
26 } |
|
27 }, |
|
28 |
|
29 _runTimer: function() { |
|
30 var anim = this; |
|
31 anim._initAttrs(); |
|
32 |
|
33 Transition._running[Y.stamp(anim)] = anim; |
|
34 anim._startTime = new Date(); |
|
35 Transition._startTimer(); |
|
36 }, |
|
37 |
|
38 _endTimer: function() { |
|
39 var anim = this; |
|
40 delete Transition._running[Y.stamp(anim)]; |
|
41 anim._startTime = null; |
|
42 }, |
|
43 |
|
44 _runFrame: function() { |
|
45 var t = new Date() - this._startTime; |
|
46 this._runAttrs(t); |
|
47 }, |
|
48 |
|
49 _runAttrs: function(time) { |
|
50 var anim = this, |
|
51 node = anim._node, |
|
52 config = anim._config, |
|
53 uid = Y.stamp(node), |
|
54 attrs = Transition._nodeAttrs[uid], |
|
55 customAttr = Transition.behaviors, |
|
56 done = false, |
|
57 allDone = false, |
|
58 data, |
|
59 name, |
|
60 attribute, |
|
61 setter, |
|
62 elapsed, |
|
63 delay, |
|
64 d, |
|
65 t, |
|
66 i; |
|
67 |
|
68 for (name in attrs) { |
|
69 if ((attribute = attrs[name]) && attribute.transition === anim) { |
|
70 d = attribute.duration; |
|
71 delay = attribute.delay; |
|
72 elapsed = (time - delay) / 1000; |
|
73 t = time; |
|
74 data = { |
|
75 type: 'propertyEnd', |
|
76 propertyName: name, |
|
77 config: config, |
|
78 elapsedTime: elapsed |
|
79 }; |
|
80 |
|
81 setter = (i in customAttr && 'set' in customAttr[i]) ? |
|
82 customAttr[i].set : Transition.DEFAULT_SETTER; |
|
83 |
|
84 done = (t >= d); |
|
85 |
|
86 if (t > d) { |
|
87 t = d; |
|
88 } |
|
89 |
|
90 if (!delay || time >= delay) { |
|
91 setter(anim, name, attribute.from, attribute.to, t - delay, d - delay, |
|
92 attribute.easing, attribute.unit); |
|
93 |
|
94 if (done) { |
|
95 delete attrs[name]; |
|
96 anim._count--; |
|
97 |
|
98 if (config[name] && config[name].on && config[name].on.end) { |
|
99 config[name].on.end.call(Y.one(node), data); |
|
100 } |
|
101 |
|
102 //node.fire('transition:propertyEnd', data); |
|
103 |
|
104 if (!allDone && anim._count <= 0) { |
|
105 allDone = true; |
|
106 anim._end(elapsed); |
|
107 anim._endTimer(); |
|
108 } |
|
109 } |
|
110 } |
|
111 |
|
112 } |
|
113 } |
|
114 }, |
|
115 |
|
116 _initAttrs: function() { |
|
117 var anim = this, |
|
118 customAttr = Transition.behaviors, |
|
119 uid = Y.stamp(anim._node), |
|
120 attrs = Transition._nodeAttrs[uid], |
|
121 attribute, |
|
122 duration, |
|
123 delay, |
|
124 easing, |
|
125 val, |
|
126 name, |
|
127 mTo, |
|
128 mFrom, |
|
129 unit, begin, end; |
|
130 |
|
131 for (name in attrs) { |
|
132 if ((attribute = attrs[name]) && attribute.transition === anim) { |
|
133 duration = attribute.duration * 1000; |
|
134 delay = attribute.delay * 1000; |
|
135 easing = attribute.easing; |
|
136 val = attribute.value; |
|
137 |
|
138 // only allow supported properties |
|
139 if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) { |
|
140 begin = (name in customAttr && 'get' in customAttr[name]) ? |
|
141 customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name); |
|
142 |
|
143 mFrom = Transition.RE_UNITS.exec(begin); |
|
144 mTo = Transition.RE_UNITS.exec(val); |
|
145 |
|
146 begin = mFrom ? mFrom[1] : begin; |
|
147 end = mTo ? mTo[1] : val; |
|
148 unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units |
|
149 |
|
150 if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) { |
|
151 unit = Transition.DEFAULT_UNIT; |
|
152 } |
|
153 |
|
154 if (typeof easing === 'string') { |
|
155 if (easing.indexOf('cubic-bezier') > -1) { |
|
156 easing = easing.substring(13, easing.length - 1).split(','); |
|
157 } else if (Transition.easings[easing]) { |
|
158 easing = Transition.easings[easing]; |
|
159 } |
|
160 } |
|
161 |
|
162 attribute.from = Number(begin); |
|
163 attribute.to = Number(end); |
|
164 attribute.unit = unit; |
|
165 attribute.easing = easing; |
|
166 attribute.duration = duration + delay; |
|
167 attribute.delay = delay; |
|
168 } else { |
|
169 delete attrs[name]; |
|
170 anim._count--; |
|
171 } |
|
172 } |
|
173 } |
|
174 }, |
|
175 |
|
176 destroy: function() { |
|
177 this.detachAll(); |
|
178 this._node = null; |
|
179 } |
|
180 }, true); |
|
181 |
|
182 Y.mix(Y.Transition, { |
|
183 _runtimeAttrs: {}, |
|
184 /* |
|
185 * Regex of properties that should use the default unit. |
|
186 * |
|
187 * @property RE_DEFAULT_UNIT |
|
188 * @static |
|
189 */ |
|
190 RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i, |
|
191 |
|
192 /* |
|
193 * The default unit to use with properties that pass the RE_DEFAULT_UNIT test. |
|
194 * |
|
195 * @property DEFAULT_UNIT |
|
196 * @static |
|
197 */ |
|
198 DEFAULT_UNIT: 'px', |
|
199 |
|
200 /* |
|
201 * Time in milliseconds passed to setInterval for frame processing |
|
202 * |
|
203 * @property intervalTime |
|
204 * @default 20 |
|
205 * @static |
|
206 */ |
|
207 intervalTime: 20, |
|
208 |
|
209 /* |
|
210 * Bucket for custom getters and setters |
|
211 * |
|
212 * @property behaviors |
|
213 * @static |
|
214 */ |
|
215 behaviors: { |
|
216 left: { |
|
217 get: function(anim, attr) { |
|
218 return Y.DOM._getAttrOffset(anim._node, attr); |
|
219 } |
|
220 } |
|
221 }, |
|
222 |
|
223 /* |
|
224 * The default setter to use when setting object properties. |
|
225 * |
|
226 * @property DEFAULT_SETTER |
|
227 * @static |
|
228 */ |
|
229 DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) { |
|
230 from = Number(from); |
|
231 to = Number(to); |
|
232 |
|
233 var node = anim._node, |
|
234 val = Transition.cubicBezier(fn, elapsed / duration); |
|
235 |
|
236 val = from + val[0] * (to - from); |
|
237 |
|
238 if (node) { |
|
239 if (att in node.style || att in Y.DOM.CUSTOM_STYLES) { |
|
240 unit = unit || ''; |
|
241 Y.DOM.setStyle(node, att, val + unit); |
|
242 } |
|
243 } else { |
|
244 anim._end(); |
|
245 } |
|
246 }, |
|
247 |
|
248 /* |
|
249 * The default getter to use when getting object properties. |
|
250 * |
|
251 * @property DEFAULT_GETTER |
|
252 * @static |
|
253 */ |
|
254 DEFAULT_GETTER: function(anim, att) { |
|
255 var node = anim._node, |
|
256 val = ''; |
|
257 |
|
258 if (att in node.style || att in Y.DOM.CUSTOM_STYLES) { |
|
259 val = Y.DOM.getComputedStyle(node, att); |
|
260 } |
|
261 |
|
262 return val; |
|
263 }, |
|
264 |
|
265 _startTimer: function() { |
|
266 if (!Transition._timer) { |
|
267 Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime); |
|
268 } |
|
269 }, |
|
270 |
|
271 _stopTimer: function() { |
|
272 clearInterval(Transition._timer); |
|
273 Transition._timer = null; |
|
274 }, |
|
275 |
|
276 /* |
|
277 * Called per Interval to handle each animation frame. |
|
278 * @method _runFrame |
|
279 * @private |
|
280 * @static |
|
281 */ |
|
282 _runFrame: function() { |
|
283 var done = true, |
|
284 anim; |
|
285 for (anim in Transition._running) { |
|
286 if (Transition._running[anim]._runFrame) { |
|
287 done = false; |
|
288 Transition._running[anim]._runFrame(); |
|
289 } |
|
290 } |
|
291 |
|
292 if (done) { |
|
293 Transition._stopTimer(); |
|
294 } |
|
295 }, |
|
296 |
|
297 cubicBezier: function(p, t) { |
|
298 var x0 = 0, |
|
299 y0 = 0, |
|
300 x1 = p[0], |
|
301 y1 = p[1], |
|
302 x2 = p[2], |
|
303 y2 = p[3], |
|
304 x3 = 1, |
|
305 y3 = 0, |
|
306 |
|
307 A = x3 - 3 * x2 + 3 * x1 - x0, |
|
308 B = 3 * x2 - 6 * x1 + 3 * x0, |
|
309 C = 3 * x1 - 3 * x0, |
|
310 D = x0, |
|
311 E = y3 - 3 * y2 + 3 * y1 - y0, |
|
312 F = 3 * y2 - 6 * y1 + 3 * y0, |
|
313 G = 3 * y1 - 3 * y0, |
|
314 H = y0, |
|
315 |
|
316 x = (((A*t) + B)*t + C)*t + D, |
|
317 y = (((E*t) + F)*t + G)*t + H; |
|
318 |
|
319 return [x, y]; |
|
320 }, |
|
321 |
|
322 easings: { |
|
323 ease: [0.25, 0, 1, 0.25], |
|
324 linear: [0, 0, 1, 1], |
|
325 'ease-in': [0.42, 0, 1, 1], |
|
326 'ease-out': [0, 0, 0.58, 1], |
|
327 'ease-in-out': [0.42, 0, 0.58, 1] |
|
328 }, |
|
329 |
|
330 _running: {}, |
|
331 _timer: null, |
|
332 |
|
333 RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/ |
|
334 }, true); |
|
335 |
|
336 Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left; |
|
337 |
|
338 Y.Transition = Transition; |
|
339 |
|
340 |
|
341 }, '3.10.3', {"requires": ["transition"]}); |