]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/transition/transition.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / transition / transition.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-native', function(Y) {
9
10 /**
11 * Provides the transition method for Node.
12 * Transition has no API of its own, but adds the transition method to Node.
13 *
14 * @module transition
15 * @requires node-style
16 */
17
18 var TRANSITION = '-webkit-transition',
19     TRANSITION_CAMEL = 'WebkitTransition',
20     TRANSITION_PROPERTY_CAMEL = 'WebkitTransitionProperty',
21     TRANSITION_PROPERTY = '-webkit-transition-property',
22     TRANSITION_DURATION = '-webkit-transition-duration',
23     TRANSITION_TIMING_FUNCTION = '-webkit-transition-timing-function',
24     TRANSITION_DELAY = '-webkit-transition-delay',
25     TRANSITION_END = 'webkitTransitionEnd',
26     ON_TRANSITION_END = 'onwebkittransitionend',
27     TRANSFORM_CAMEL = 'WebkitTransform',
28
29     EMPTY_OBJ = {},
30
31 /**
32  * A class for constructing transition instances.
33  * Adds the "transition" method to Node.
34  * @class Transition
35  * @constructor
36  */
37
38 Transition = function() {
39     this.init.apply(this, arguments);
40 };
41
42 Transition.fx = {};
43 Transition.toggles = {};
44
45 Transition._hasEnd = {};
46
47 Transition._toCamel = function(property) {
48     property = property.replace(/-([a-z])/gi, function(m0, m1) {
49         return m1.toUpperCase();
50     });
51
52     return property;
53 };
54
55 Transition._toHyphen = function(property) {
56     property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
57         var str = '';
58         if (m1) {
59             str += '-' + m1.toLowerCase();
60         }
61         str += m2;
62         
63         if (m3) {
64             str += '-' + m3.toLowerCase();
65         }
66
67         return str;
68     }); 
69
70     return property;
71 };
72
73
74 Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
75
76 Transition.useNative = false;
77
78 if (TRANSITION in Y.config.doc.documentElement.style) {
79     Transition.useNative = true;
80     Transition.supported = true; // TODO: remove
81 }
82
83 Y.Node.DOM_EVENTS[TRANSITION_END] = 1; 
84
85 Transition.NAME = 'transition';
86
87 Transition.DEFAULT_EASING = 'ease';
88 Transition.DEFAULT_DURATION = 0.5;
89 Transition.DEFAULT_DELAY = 0;
90
91 Transition._nodeAttrs = {};
92
93 Transition.prototype = {
94     constructor: Transition,
95     init: function(node, config) {
96         var anim = this;
97         anim._node = node;
98         if (!anim._running && config) {
99             anim._config = config;
100             node._transition = anim; // cache for reuse
101
102             anim._duration = ('duration' in config) ?
103                 config.duration: anim.constructor.DEFAULT_DURATION;
104
105             anim._delay = ('delay' in config) ?
106                 config.delay: anim.constructor.DEFAULT_DELAY;
107
108             anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
109             anim._count = 0; // track number of animated properties
110             anim._running = false;
111
112         }
113
114         return anim;
115     },
116
117     addProperty: function(prop, config) {
118         var anim = this,
119             node = this._node,
120             uid = Y.stamp(node),
121             nodeInstance = Y.one(node),
122             attrs = Transition._nodeAttrs[uid],
123             computed,
124             compareVal,
125             dur,
126             attr,
127             val;
128
129         if (!attrs) {
130             attrs = Transition._nodeAttrs[uid] = {};
131         }
132
133         attr = attrs[prop];
134
135         // might just be a value
136         if (config && config.value !== undefined) {
137             val = config.value;
138         } else if (config !== undefined) {
139             val = config; 
140             config = EMPTY_OBJ;
141         }
142
143         if (typeof val === 'function') {
144             val = val.call(nodeInstance, nodeInstance);
145         }
146
147         if (attr && attr.transition) {
148             // take control if another transition owns this property
149             if (attr.transition !== anim) {
150                 attr.transition._count--; // remapping attr to this transition
151             }
152         } 
153
154         anim._count++; // properties per transition
155
156         // make 0 async and fire events
157         dur = ((typeof config.duration != 'undefined') ? config.duration :
158                     anim._duration) || 0.0001;
159
160         attrs[prop] = {
161             value: val,
162             duration: dur,
163             delay: (typeof config.delay != 'undefined') ? config.delay :
164                     anim._delay,
165
166             easing: config.easing || anim._easing,
167
168             transition: anim
169         };
170
171         // native end event doesnt fire when setting to same value
172         // supplementing with timer
173         // val may be a string or number (height: 0, etc), but computedStyle is always string
174         computed = Y.DOM.getComputedStyle(node, prop);
175         compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
176
177         if (Transition.useNative && compareVal === val) {
178             setTimeout(function() {
179                 anim._onNativeEnd.call(node, {
180                     propertyName: prop,
181                     elapsedTime: dur
182                 });
183             }, dur * 1000);
184         }
185     },
186
187     removeProperty: function(prop) {
188         var anim = this,
189             attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
190
191         if (attrs && attrs[prop]) {
192             delete attrs[prop];
193             anim._count--;
194         }
195
196     },
197
198     initAttrs: function(config) {
199         var attr,
200             node = this._node;
201
202         if (config.transform && !config[TRANSFORM_CAMEL]) {
203             config[TRANSFORM_CAMEL] = config.transform;
204             delete config.transform; // TODO: copy
205         }
206
207         for (attr in config) {
208             if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
209                 this.addProperty(attr, config[attr]);
210
211                 // when size is auto or % webkit starts from zero instead of computed 
212                 // (https://bugs.webkit.org/show_bug.cgi?id=16020)
213                 // TODO: selective set
214                 if (node.style[attr] === '') {
215                     Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
216                 }
217             }
218         }
219     },
220
221     /**
222      * Starts or an animation.
223      * @method run
224      * @chainable
225      * @private
226      */    
227     run: function(callback) {
228         var anim = this,
229             node = anim._node,
230             config = anim._config,
231             data = {
232                 type: 'transition:start',
233                 config: config
234             };
235
236
237         if (!anim._running) {
238             anim._running = true;
239
240             //anim._node.fire('transition:start', data);
241
242             if (config.on && config.on.start) {
243                 config.on.start.call(Y.one(node), data);
244             }
245
246             anim.initAttrs(anim._config);
247
248             anim._callback = callback;
249             anim._start();
250         }
251
252
253         return anim;
254     },
255
256     _start: function() {
257         this._runNative();
258     },
259
260     _prepDur: function(dur) {
261         dur = parseFloat(dur);
262
263         return dur + 's';
264     },
265
266     _runNative: function(time) {
267         var anim = this,
268             node = anim._node,
269             uid = Y.stamp(node),
270             style = node.style,
271             computed = getComputedStyle(node),
272             attrs = Transition._nodeAttrs[uid],
273             cssText = '',
274             cssTransition = computed[TRANSITION_PROPERTY],
275
276             transitionText = TRANSITION_PROPERTY + ': ',
277             duration = TRANSITION_DURATION + ': ',
278             easing = TRANSITION_TIMING_FUNCTION + ': ',
279             delay = TRANSITION_DELAY + ': ',
280             hyphy,
281             attr,
282             name;
283
284         // preserve existing transitions
285         if (cssTransition !== 'all') {
286             transitionText += cssTransition + ',';
287             duration += computed[TRANSITION_DURATION] + ',';
288             easing += computed[TRANSITION_TIMING_FUNCTION] + ',';
289             delay += computed[TRANSITION_DELAY] + ',';
290
291         }
292
293         // run transitions mapped to this instance
294         for (name in attrs) {
295             hyphy = Transition._toHyphen(name);
296             attr = attrs[name];
297             if (attrs.hasOwnProperty(name) && attr.transition === anim) {
298                 if (name in node.style) { // only native styles allowed
299                     duration += anim._prepDur(attr.duration) + ',';
300                     delay += anim._prepDur(attr.delay) + ',';
301                     easing += (attr.easing) + ',';
302
303                     transitionText += hyphy + ',';
304                     cssText += hyphy + ': ' + attr.value + '; ';
305                 } else {
306                     this.removeProperty(name);
307                 }
308             }
309         }
310
311         transitionText = transitionText.replace(/,$/, ';');
312         duration = duration.replace(/,$/, ';');
313         easing = easing.replace(/,$/, ';');
314         delay = delay.replace(/,$/, ';');
315
316         // only one native end event per node
317         if (!Transition._hasEnd[uid]) {
318             //anim._detach = Y.on(TRANSITION_END, anim._onNativeEnd, node);
319             //node[ON_TRANSITION_END] = anim._onNativeEnd;
320             node.addEventListener(TRANSITION_END, anim._onNativeEnd, false);
321             Transition._hasEnd[uid] = true;
322
323         }
324         
325         //setTimeout(function() { // allow updates to apply (size fix, onstart, etc)
326             style.cssText += transitionText + duration + easing + delay + cssText;
327         //}, 1);
328
329     },
330
331     _end: function(elapsed) {
332         var anim = this,
333             node = anim._node,
334             callback = anim._callback,
335             config = anim._config,
336             data = {
337                 type: 'transition:end',
338                 config: config,
339                 elapsedTime: elapsed 
340             },
341
342             nodeInstance = Y.one(node); 
343
344         anim._running = false;
345         anim._callback = null;
346
347         if (node) {
348             if (config.on && config.on.end) {
349                 setTimeout(function() { // IE: allow previous update to finish
350                     config.on.end.call(nodeInstance, data);
351
352                     // nested to ensure proper fire order
353                     if (callback) {
354                         callback.call(nodeInstance, data);
355                     }
356
357                 }, 1);
358             } else if (callback) {
359                 setTimeout(function() { // IE: allow previous update to finish
360                     callback.call(nodeInstance, data);
361                 }, 1);
362             }
363             //node.fire('transition:end', data);
364         }
365
366     },
367
368     _endNative: function(name) {
369         var node = this._node,
370             value = node.ownerDocument.defaultView.getComputedStyle(node, '')[TRANSITION_PROPERTY];
371
372         if (typeof value === 'string') {
373             value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
374             value = value.replace(/^,|,$/, '');
375             node.style[TRANSITION_CAMEL] = value;
376         }
377     },
378
379     _onNativeEnd: function(e) {
380         var node = this,
381             uid = Y.stamp(node),
382             event = e,//e._event,
383             name = Transition._toCamel(event.propertyName),
384             elapsed = event.elapsedTime,
385             attrs = Transition._nodeAttrs[uid],
386             attr = attrs[name],
387             anim = (attr) ? attr.transition : null,
388             data,
389             config;
390
391         if (anim) {
392             anim.removeProperty(name);
393             anim._endNative(name);
394             config = anim._config[name];
395
396             data = {
397                 type: 'propertyEnd',
398                 propertyName: name,
399                 elapsedTime: elapsed,
400                 config: config
401             };
402
403             if (config && config.on && config.on.end) {
404                 config.on.end.call(Y.one(node), data);
405             }
406
407             //node.fire('transition:propertyEnd', data);
408
409             if (anim._count <= 0)  { // after propertyEnd fires
410                 anim._end(elapsed);
411             }
412         }
413     },
414
415     destroy: function() {
416         var anim = this;
417         /*
418         if (anim._detach) {
419             anim._detach.detach();
420         }
421         */
422         //anim._node[ON_TRANSITION_END] = null;
423         node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
424         anim._node = null;
425     }
426 };
427
428 Y.Transition = Transition;
429 Y.TransitionNative = Transition; // TODO: remove
430
431 /** 
432  *   Animate one or more css properties to a given value. Requires the "transition" module.
433  *   <pre>example usage:
434  *       Y.one('#demo').transition({
435  *           duration: 1, // in seconds, default is 0.5
436  *           easing: 'ease-out', // default is 'ease'
437  *           delay: '1', // delay start for 1 second, default is 0
438  *
439  *           height: '10px',
440  *           width: '10px',
441  *
442  *           opacity: { // per property
443  *               value: 0,
444  *               duration: 2,
445  *               delay: 2,
446  *               easing: 'ease-in'
447  *           }
448  *       });
449  *   </pre>
450  *   @for Node
451  *   @method transition
452  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
453  *   @param {Function} callback A function to run after the transition has completed. 
454  *   @chainable
455 */
456 Y.Node.prototype.transition = function(name, config, callback) {
457     var 
458         transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
459         anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
460         fxConfig,
461         prop;
462     
463     if (typeof name === 'string') { // named effect, pull config from registry
464         if (typeof config === 'function') {
465             callback = config;
466             config = null;
467         }
468
469         fxConfig = Transition.fx[name];
470
471         if (config && typeof config !== 'boolean') {
472             config = Y.clone(config);
473
474             for (prop in fxConfig) {
475                 if (fxConfig.hasOwnProperty(prop)) {
476                     if (! (prop in config)) {
477                         config[prop] = fxConfig[prop]; 
478                     }
479                 }
480             }
481         } else {
482             config = fxConfig;
483         }
484
485     } else { // name is a config, config is a callback or undefined
486         callback = config;
487         config = name;
488     }
489
490     if (anim && !anim._running) {
491         anim.init(this, config);
492     } else {
493         anim = new Transition(this._node, config);
494     }
495
496     anim.run(callback);
497     return this;
498 };
499
500 Y.Node.prototype.show = function(name, config, callback) {
501     this._show(); // show prior to transition
502     if (name && Y.Transition) {
503         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
504             if (typeof config === 'function') {
505                 callback = config;
506                 config = name;
507             }
508             name = this.SHOW_TRANSITION; 
509         }    
510         this.transition(name, config, callback);
511     }    
512     return this;
513 };
514
515 var _wrapCallBack = function(anim, fn, callback) {
516     return function() {
517         if (fn) {
518             fn.call(anim);
519         }
520         if (callback) {
521             callback.apply(anim._node, arguments);
522         }
523     };
524 };
525
526 Y.Node.prototype.hide = function(name, config, callback) {
527     if (name && Y.Transition) {
528         if (typeof config === 'function') {
529             callback = config;
530             config = null;
531         }
532
533         callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
534         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
535             if (typeof config === 'function') {
536                 callback = config;
537                 config = name;
538             }
539             name = this.HIDE_TRANSITION; 
540         }    
541         this.transition(name, config, callback);
542     } else {
543         this._hide();
544     }    
545     return this;
546 }; 
547
548 /** 
549  *   Animate one or more css properties to a given value. Requires the "transition" module.
550  *   <pre>example usage:
551  *       Y.all('.demo').transition({
552  *           duration: 1, // in seconds, default is 0.5
553  *           easing: 'ease-out', // default is 'ease'
554  *           delay: '1', // delay start for 1 second, default is 0
555  *
556  *           height: '10px',
557  *           width: '10px',
558  *
559  *           opacity: { // per property
560  *               value: 0,
561  *               duration: 2,
562  *               delay: 2,
563  *               easing: 'ease-in'
564  *           }
565  *       });
566  *   </pre>
567  *   @for NodeList
568  *   @method transition
569  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
570  *   @param {Function} callback A function to run after the transition has completed. The callback fires
571  *       once per item in the NodeList.
572  *   @chainable
573 */
574 Y.NodeList.prototype.transition = function(config, callback) {
575     var nodes = this._nodes,
576         i = 0,
577         node;
578
579     while ((node = nodes[i++])) {
580         Y.one(node).transition(config, callback);
581     }
582
583     return this;
584 };
585
586 Y.Node.prototype.toggleView = function(name, on) {
587     var callback;
588     this._toggles = this._toggles || [];
589
590     if (typeof name == 'boolean') { // no transition, just toggle
591         on = name;
592     }
593     if (typeof on === 'undefined' && name in this._toggles) {
594         on = ! this._toggles[name];
595     }
596
597     on = (on) ? 1 : 0;
598
599     if (on) {
600         this._show();
601     }  else {
602         callback = _wrapCallBack(anim, this._hide);
603     }
604
605     this._toggles[name] = on;
606     this.transition(Y.Transition.toggles[name][on], callback);
607 };
608
609 Y.NodeList.prototype.toggleView = function(config, callback) {
610     var nodes = this._nodes,
611         i = 0,
612         node;
613
614     while ((node = nodes[i++])) {
615         Y.one(node).toggleView(config, callback);
616     }
617
618     return this;
619 };
620
621 Y.mix(Transition.fx, {
622     fadeOut: {
623         opacity: 0,
624         duration: 0.5,
625         easing: 'ease-out'
626     },
627
628     fadeIn: {
629         opacity: 1,
630         duration: 0.5,
631         easing: 'ease-in'
632     },
633
634     sizeOut: {
635         height: 0,
636         width: 0,
637         duration: 0.75,
638         easing: 'ease-out'
639     },
640
641     sizeIn: {
642         height: function(node) {
643             return node.get('scrollHeight') + 'px';
644         },
645         width: function(node) {
646             return node.get('scrollWidth') + 'px';
647         },
648         duration: 0.5,
649         easing: 'ease-in',
650         
651         on: {
652             start: function() {
653                 var overflow = this.getStyle('overflow');
654                 if (overflow !== 'hidden') { // enable scrollHeight/Width
655                     this.setStyle('overflow', 'hidden');
656                     this._transitionOverflow = overflow;
657                 }
658             },
659
660             end: function() {
661                 if (this._transitionOverflow) { // revert overridden value
662                     this.setStyle('overflow', this._transitionOverflow);
663                 }
664             }
665         } 
666     }
667 });
668
669 Y.mix(Transition.toggles, {
670     size: ['sizeIn', 'sizeOut'],
671     fade: ['fadeOut', 'fadeIn']
672 });
673
674
675 }, '3.3.0' ,{requires:['node-base']});
676 YUI.add('transition-timer', function(Y) {
677
678 /*
679 * The Transition Utility provides an API for creating advanced transitions.
680 * @module transition
681 */
682
683 /*
684 * Provides the base Transition class, for animating numeric properties.
685 *
686 * @module transition
687 * @submodule transition-timer
688 */
689
690
691 var Transition = Y.Transition;
692
693 Y.mix(Transition.prototype, {
694     _start: function() {
695         if (Transition.useNative) {
696             this._runNative();
697         } else {
698             this._runTimer();
699         }
700     },
701
702     _runTimer: function() {
703         var anim = this;
704         anim._initAttrs();
705
706         Transition._running[Y.stamp(anim)] = anim;
707         anim._startTime = new Date();
708         Transition._startTimer();
709     },
710
711     _endTimer: function() {
712         var anim = this;
713         delete Transition._running[Y.stamp(anim)];
714         anim._startTime = null;
715     },
716
717     _runFrame: function() {
718         var t = new Date() - this._startTime;
719         this._runAttrs(t);
720     },
721
722     _runAttrs: function(time) {
723         var anim = this,
724             node = anim._node,
725             config = anim._config,
726             uid = Y.stamp(node),
727             attrs = Transition._nodeAttrs[uid],
728             customAttr = Transition.behaviors,
729             done = false,
730             allDone = false,
731             data,
732             name,
733             attribute,
734             setter,
735             elapsed,
736             delay,
737             d,
738             t,
739             i;
740
741         for (name in attrs) {
742             attribute = attrs[name];
743             if ((attribute && attribute.transition === anim)) {
744                 d = attribute.duration;
745                 delay = attribute.delay;
746                 elapsed = (time - delay) / 1000;
747                 t = time;
748                 data = {
749                     type: 'propertyEnd',
750                     propertyName: name,
751                     config: config,
752                     elapsedTime: elapsed
753                 };
754
755                 setter = (i in customAttr && 'set' in customAttr[i]) ?
756                         customAttr[i].set : Transition.DEFAULT_SETTER;
757
758                 done = (t >= d);
759
760                 if (t > d) {
761                     t = d;
762                 }
763
764                 if (!delay || time >= delay) {
765                     setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
766                         attribute.easing, attribute.unit); 
767
768                     if (done) {
769                         delete attrs[name];
770                         anim._count--;
771
772                         if (config[name] && config[name].on && config[name].on.end) {
773                             config[name].on.end.call(Y.one(node), data);
774                         }
775
776                         //node.fire('transition:propertyEnd', data);
777
778                         if (!allDone && anim._count <= 0) {
779                             allDone = true;
780                             anim._end(elapsed);
781                             anim._endTimer();
782                         }
783                     }
784                 }
785
786             }
787         }
788     },
789
790     _initAttrs: function() {
791         var anim = this,
792             customAttr = Transition.behaviors,
793             uid = Y.stamp(anim._node),
794             attrs = Transition._nodeAttrs[uid],
795             attribute,
796             duration,
797             delay,
798             easing,
799             val,
800             name,
801             mTo,
802             mFrom,
803             unit, begin, end;
804
805         for (name in attrs) {
806             attribute = attrs[name];
807             if (attrs.hasOwnProperty(name) && (attribute && attribute.transition === anim)) {
808                 duration = attribute.duration * 1000;
809                 delay = attribute.delay * 1000;
810                 easing = attribute.easing;
811                 val = attribute.value;
812
813                 // only allow supported properties
814                 if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
815                     begin = (name in customAttr && 'get' in customAttr[name])  ?
816                             customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
817
818                     mFrom = Transition.RE_UNITS.exec(begin);
819                     mTo = Transition.RE_UNITS.exec(val);
820
821                     begin = mFrom ? mFrom[1] : begin;
822                     end = mTo ? mTo[1] : val;
823                     unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
824
825                     if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
826                         unit = Transition.DEFAULT_UNIT;
827                     }
828
829                     if (typeof easing === 'string') {
830                         if (easing.indexOf('cubic-bezier') > -1) {
831                             easing = easing.substring(13, easing.length - 1).split(',');
832                         } else if (Transition.easings[easing]) {
833                             easing = Transition.easings[easing];
834                         }
835                     }
836
837                     attribute.from = Number(begin);
838                     attribute.to = Number(end);
839                     attribute.unit = unit;
840                     attribute.easing = easing;
841                     attribute.duration = duration + delay;
842                     attribute.delay = delay;
843                 } else {
844                     delete attrs[name];
845                     anim._count--;
846                 }
847             }
848         }
849     },
850
851     destroy: function() {
852         this.detachAll();
853         this._node = null;
854     }
855 }, true);
856
857 Y.mix(Y.Transition, {
858     _runtimeAttrs: {},
859     /*
860      * Regex of properties that should use the default unit.
861      *
862      * @property RE_DEFAULT_UNIT
863      * @static
864      */
865     RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
866
867     /*
868      * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
869      *
870      * @property DEFAULT_UNIT
871      * @static
872      */
873     DEFAULT_UNIT: 'px',
874
875     /*
876      * Time in milliseconds passed to setInterval for frame processing 
877      *
878      * @property intervalTime
879      * @default 20
880      * @static
881      */
882     intervalTime: 20,
883
884     /*
885      * Bucket for custom getters and setters
886      *
887      * @property behaviors
888      * @static
889      */
890     behaviors: {
891         left: {
892             get: function(anim, attr) {
893                 return Y.DOM._getAttrOffset(anim._node, attr);
894             }
895         }
896     },
897
898     /*
899      * The default setter to use when setting object properties.
900      *
901      * @property DEFAULT_SETTER
902      * @static
903      */
904     DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
905         from = Number(from);
906         to = Number(to);
907
908         var node = anim._node,
909             val = Transition.cubicBezier(fn, elapsed / duration);
910
911         val = from + val[0] * (to - from);
912
913         if (node) {
914             if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
915                 unit = unit || '';
916                 Y.DOM.setStyle(node, att, val + unit);
917             }
918         } else {
919             anim._end();
920         }
921     },
922
923     /*
924      * The default getter to use when getting object properties.
925      *
926      * @property DEFAULT_GETTER
927      * @static
928      */
929     DEFAULT_GETTER: function(anim, att) {
930         var node = anim._node,
931             val = '';
932
933         if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
934             val = Y.DOM.getComputedStyle(node, att);
935         }
936
937         return val;
938     },
939
940     _startTimer: function() {
941         if (!Transition._timer) {
942             Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
943         }
944     },
945
946     _stopTimer: function() {
947         clearInterval(Transition._timer);
948         Transition._timer = null;
949     },
950
951     /*
952      * Called per Interval to handle each animation frame.
953      * @method _runFrame
954      * @private
955      * @static
956      */    
957     _runFrame: function() {
958         var done = true,
959             anim;
960         for (anim in Transition._running) {
961             if (Transition._running[anim]._runFrame) {
962                 done = false;
963                 Transition._running[anim]._runFrame();
964             }
965         }
966
967         if (done) {
968             Transition._stopTimer();
969         }
970     },
971
972     cubicBezier: function(p, t) {
973         var x0 = 0,
974             y0 = 0,
975             x1 = p[0],
976             y1 = p[1],
977             x2 = p[2],
978             y2 = p[3],
979             x3 = 1,
980             y3 = 0,
981
982             A = x3 - 3 * x2 + 3 * x1 - x0,
983             B = 3 * x2 - 6 * x1 + 3 * x0,
984             C = 3 * x1 - 3 * x0,
985             D = x0,
986             E = y3 - 3 * y2 + 3 * y1 - y0,
987             F = 3 * y2 - 6 * y1 + 3 * y0,
988             G = 3 * y1 - 3 * y0,
989             H = y0,
990
991             x = (((A*t) + B)*t + C)*t + D,
992             y = (((E*t) + F)*t + G)*t + H;
993
994         return [x, y];
995     },
996
997     easings: {
998         ease: [0.25, 0, 1, 0.25],
999         linear: [0, 0, 1, 1],
1000         'ease-in': [0.42, 0, 1, 1],
1001         'ease-out': [0, 0, 0.58, 1],
1002         'ease-in-out': [0.42, 0, 0.58, 1]
1003     },
1004
1005     _running: {},
1006     _timer: null,
1007
1008     RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
1009 }, true); 
1010
1011 Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
1012
1013 Y.Transition = Transition;
1014
1015
1016 }, '3.3.0' ,{requires:['transition-native', 'node-style']});
1017
1018
1019 YUI.add('transition', function(Y){}, '3.3.0' ,{use:['transition-native', 'transition-timer']});
1020