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