transition-debug.js revision 7f03c81c9c42b32e09a911682e00adb57f0985b9
10139N/AYUI.add('transition-native', function(Y) {
10139N/A
10139N/A/**
10139N/A* Provides the transition method for Node.
13600N/A* Transition has no API of its own, but adds the transition method to Node.
10139N/A*
10139N/A* @module transition
10139N/A* @requires node-style
10139N/A*/
10139N/A
10139N/Avar TRANSITION = '-webkit-transition',
10139N/A TRANSITION_CAMEL = 'WebkitTransition',
16952N/A TRANSITION_PROPERTY_CAMEL = 'WebkitTransitionProperty',
16952N/A TRANSITION_PROPERTY = '-webkit-transition-property',
10139N/A TRANSITION_DURATION = '-webkit-transition-duration',
10139N/A TRANSITION_TIMING_FUNCTION = '-webkit-transition-timing-function',
10139N/A TRANSITION_DELAY = '-webkit-transition-delay',
10139N/A TRANSITION_END = 'webkitTransitionEnd',
10139N/A ON_TRANSITION_END = 'onwebkittransitionend',
16207N/A TRANSFORM_CAMEL = 'WebkitTransform',
10139N/A
10139N/A EMPTY_OBJ = {},
15536N/A
15536N/A/**
15536N/A * A class for constructing transition instances.
15536N/A * Adds the "transition" method to Node.
15536N/A * @class Transition
16554N/A * @constructor
15761N/A */
15761N/A
15761N/ATransition = function() {
15761N/A this.init.apply(this, arguments);
16554N/A};
16554N/A
16554N/ATransition.fx = {};
10139N/ATransition.toggles = {};
16633N/A
11999N/ATransition._hasEnd = {};
15536N/A
10139N/ATransition._toCamel = function(property) {
10139N/A property = property.replace(/-([a-z])/gi, function(m0, m1) {
10139N/A return m1.toUpperCase();
15536N/A });
10139N/A
13898N/A return property;
13898N/A};
15536N/A
10139N/ATransition._toHyphen = function(property) {
16437N/A property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
16437N/A var str = '';
16437N/A if (m1) {
10544N/A str += '-' + m1.toLowerCase();
12830N/A }
12830N/A str += m2;
15536N/A
12830N/A if (m3) {
13914N/A str += '-' + m3.toLowerCase();
13915N/A }
15536N/A
13914N/A return str;
16712N/A });
16712N/A
15536N/A return property;
14425N/A};
16680N/A
15536N/A
15190N/ATransition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
16597N/A
15536N/ATransition.useNative = false;
15536N/A
15216N/Aif (TRANSITION in Y.config.doc.documentElement.style) {
15418N/A Transition.useNative = true;
15536N/A Transition.supported = true; // TODO: remove
15418N/A}
16554N/A
16554N/AY.Node.DOM_EVENTS[TRANSITION_END] = 1;
16554N/A
16554N/ATransition.NAME = 'transition';
16554N/A
16050N/ATransition.DEFAULT_EASING = 'ease';
15536N/ATransition.DEFAULT_DURATION = 0.5;
15516N/ATransition.DEFAULT_DELAY = 0;
16597N/A
16050N/ATransition._nodeAttrs = {};
15516N/A
15536N/ATransition.prototype = {
15536N/A constructor: Transition,
15529N/A init: function(node, config) {
15536N/A var anim = this;
15536N/A anim._node = node;
15529N/A if (!anim._running && config) {
16554N/A anim._config = config;
15761N/A node._transition = anim; // cache for reuse
15761N/A
15761N/A anim._duration = ('duration' in config) ?
15761N/A config.duration: anim.constructor.DEFAULT_DURATION;
15761N/A
15761N/A anim._delay = ('delay' in config) ?
15761N/A config.delay: anim.constructor.DEFAULT_DELAY;
16279N/A
16279N/A anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
16279N/A anim._count = 0; // track number of animated properties
16279N/A anim._running = false;
16020N/A
16020N/A }
16020N/A
16020N/A return anim;
16020N/A },
16689N/A
16549N/A addProperty: function(prop, config) {
16549N/A var anim = this,
16601N/A node = this._node,
16549N/A uid = Y.stamp(node),
16532N/A nodeInstance = Y.one(node),
16766N/A attrs = Transition._nodeAttrs[uid],
16766N/A computed,
16766N/A compareVal,
16766N/A dur,
16766N/A attr,
16801N/A val;
16801N/A
16801N/A if (!attrs) {
16916N/A attrs = Transition._nodeAttrs[uid] = {};
16916N/A }
16916N/A
15536N/A attr = attrs[prop];
10139N/A
10139N/A // might just be a value
10139N/A if (config && config.value !== undefined) {
10139N/A val = config.value;
10139N/A } else if (config !== undefined) {
10139N/A val = config;
10139N/A config = EMPTY_OBJ;
10139N/A }
10139N/A
10139N/A if (typeof val === 'function') {
10139N/A val = val.call(nodeInstance, nodeInstance);
10139N/A }
16554N/A
10139N/A if (attr && attr.transition) {
13898N/A // take control if another transition owns this property
13898N/A if (attr.transition !== anim) {
13898N/A attr.transition._count--; // remapping attr to this transition
10139N/A }
10139N/A }
10139N/A
10139N/A anim._count++; // properties per transition
10139N/A
10139N/A // make 0 async and fire events
10139N/A dur = ((typeof config.duration != 'undefined') ? config.duration :
10139N/A anim._duration) || 0.0001;
10139N/A
10139N/A attrs[prop] = {
10139N/A value: val,
10139N/A duration: dur,
10139N/A delay: (typeof config.delay != 'undefined') ? config.delay :
10139N/A anim._delay,
10139N/A
10139N/A easing: config.easing || anim._easing,
10139N/A
10139N/A transition: anim
10139N/A };
10139N/A
10139N/A // native end event doesnt fire when setting to same value
10139N/A // supplementing with timer
10139N/A // val may be a string or number (height: 0, etc), but computedStyle is always string
10139N/A computed = Y.DOM.getComputedStyle(node, prop);
10139N/A compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
10139N/A
10139N/A if (Transition.useNative && compareVal === val) {
10139N/A setTimeout(function() {
16554N/A anim._onNativeEnd.call(node, {
15761N/A propertyName: prop,
15761N/A elapsedTime: dur
10139N/A });
15761N/A }, dur * 1000);
10139N/A }
10139N/A },
10139N/A
16050N/A removeProperty: function(prop) {
16061N/A var anim = this,
16061N/A attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
16050N/A
16061N/A if (attrs && attrs[prop]) {
16061N/A delete attrs[prop];
16061N/A anim._count--;
16050N/A }
16061N/A
10139N/A },
10139N/A
15536N/A initAttrs: function(config) {
10139N/A var attr,
15536N/A node = this._node;
15536N/A
10139N/A if (config.transform && !config[TRANSFORM_CAMEL]) {
15536N/A config[TRANSFORM_CAMEL] = config.transform;
15536N/A delete config.transform; // TODO: copy
10139N/A }
10139N/A
15536N/A for (attr in config) {
10139N/A if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
15536N/A this.addProperty(attr, config[attr]);
15536N/A
15536N/A // when size is auto or % webkit starts from zero instead of computed
16279N/A // (https://bugs.webkit.org/show_bug.cgi?id=16020)
16532N/A // TODO: selective set
16549N/A if (node.style[attr] === '') {
16050N/A Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
16020N/A }
16020N/A }
16020N/A }
10139N/A },
16554N/A
15761N/A /**
15761N/A * Starts or an animation.
16766N/A * @method run
15761N/A * @chainable
15761N/A * @private
16801N/A */
16916N/A run: function(callback) {
16801N/A var anim = this,
16554N/A node = anim._node,
16554N/A config = anim._config,
16554N/A data = {
16554N/A type: 'transition:start',
10139N/A config: config
10139N/A };
10139N/A
10139N/A
10139N/A if (!anim._running) {
10139N/A anim._running = true;
10139N/A
10139N/A //anim._node.fire('transition:start', data);
10139N/A
10139N/A if (config.on && config.on.start) {
10139N/A config.on.start.call(Y.one(node), data);
10139N/A }
10139N/A
10139N/A anim.initAttrs(anim._config);
10139N/A
10139N/A anim._callback = callback;
10139N/A anim._start();
15536N/A }
10139N/A
10139N/A
10139N/A return anim;
10139N/A },
10139N/A
10139N/A _start: function() {
13898N/A this._runNative();
13898N/A },
14526N/A
13898N/A _prepDur: function(dur) {
14124N/A dur = parseFloat(dur);
10139N/A
13898N/A return dur + 's';
10139N/A },
13898N/A
13898N/A _runNative: function(time) {
15189N/A var anim = this,
13898N/A node = anim._node,
16554N/A uid = Y.stamp(node),
16554N/A style = node.style,
16554N/A computed = getComputedStyle(node),
16554N/A attrs = Transition._nodeAttrs[uid],
16656N/A cssText = '',
10139N/A cssTransition = computed[TRANSITION_PROPERTY],
10139N/A
16554N/A transitionText = TRANSITION_PROPERTY + ': ',
10139N/A duration = TRANSITION_DURATION + ': ',
10139N/A easing = TRANSITION_TIMING_FUNCTION + ': ',
10139N/A delay = TRANSITION_DELAY + ': ',
10139N/A hyphy,
10139N/A attr,
10139N/A name;
10139N/A
10139N/A // preserve existing transitions
10139N/A if (cssTransition !== 'all') {
13898N/A transitionText += cssTransition + ',';
13898N/A duration += computed[TRANSITION_DURATION] + ',';
13898N/A easing += computed[TRANSITION_TIMING_FUNCTION] + ',';
13898N/A delay += computed[TRANSITION_DELAY] + ',';
13898N/A
10139N/A }
16554N/A
16554N/A // run transitions mapped to this instance
16554N/A for (name in attrs) {
16554N/A hyphy = Transition._toHyphen(name);
16554N/A attr = attrs[name];
16554N/A if (attrs.hasOwnProperty(name) && attr.transition === anim) {
16554N/A if (name in node.style) { // only native styles allowed
13898N/A duration += anim._prepDur(attr.duration) + ',';
13898N/A delay += anim._prepDur(attr.delay) + ',';
13898N/A easing += (attr.easing) + ',';
14124N/A
15536N/A transitionText += hyphy + ',';
14124N/A cssText += hyphy + ': ' + attr.value + '; ';
13898N/A } else {
12834N/A this.removeProperty(name);
10139N/A }
10139N/A }
10139N/A }
10139N/A
13898N/A transitionText = transitionText.replace(/,$/, ';');
13898N/A duration = duration.replace(/,$/, ';');
13898N/A easing = easing.replace(/,$/, ';');
13898N/A delay = delay.replace(/,$/, ';');
13898N/A
13898N/A // only one native end event per node
13898N/A if (!Transition._hasEnd[uid]) {
13898N/A //anim._detach = Y.on(TRANSITION_END, anim._onNativeEnd, node);
13898N/A //node[ON_TRANSITION_END] = anim._onNativeEnd;
13898N/A node.addEventListener(TRANSITION_END, anim._onNativeEnd, false);
13898N/A Transition._hasEnd[uid] = true;
13898N/A
13898N/A }
13898N/A
13898N/A //setTimeout(function() { // allow updates to apply (size fix, onstart, etc)
13898N/A style.cssText += transitionText + duration + easing + delay + cssText;
13898N/A //}, 1);
13898N/A
13898N/A },
14376N/A
13898N/A _end: function(elapsed) {
13898N/A var anim = this,
13898N/A node = anim._node,
13898N/A callback = anim._callback,
14376N/A config = anim._config,
13898N/A data = {
13898N/A type: 'transition:end',
13898N/A config: config,
10139N/A elapsedTime: elapsed
10139N/A },
10139N/A
10139N/A nodeInstance = Y.one(node);
10139N/A
10139N/A anim._running = false;
10139N/A anim._callback = null;
10139N/A
10139N/A if (node) {
10139N/A if (config.on && config.on.end) {
15536N/A setTimeout(function() { // IE: allow previous update to finish
13898N/A config.on.end.call(nodeInstance, data);
10139N/A
10139N/A // nested to ensure proper fire order
10544N/A if (callback) {
15536N/A callback.call(nodeInstance, data);
10544N/A }
13898N/A
13898N/A }, 1);
13898N/A } else if (callback) {
13898N/A setTimeout(function() { // IE: allow previous update to finish
13898N/A callback.call(nodeInstance, data);
13898N/A }, 1);
13898N/A }
13898N/A //node.fire('transition:end', data);
13898N/A }
16617N/A
16617N/A },
16617N/A
16617N/A _endNative: function(name) {
16617N/A var node = this._node,
16617N/A value = node.ownerDocument.defaultView.getComputedStyle(node, '')[TRANSITION_PROPERTY];
16617N/A
16617N/A if (typeof value === 'string') {
16617N/A value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
16617N/A value = value.replace(/^,|,$/, '');
16617N/A node.style[TRANSITION_CAMEL] = value;
15536N/A }
14376N/A },
13898N/A
13898N/A _onNativeEnd: function(e) {
13898N/A var node = this,
13898N/A uid = Y.stamp(node),
15536N/A event = e,//e._event,
15536N/A name = Transition._toCamel(event.propertyName),
15536N/A elapsed = event.elapsedTime,
15536N/A attrs = Transition._nodeAttrs[uid],
14376N/A attr = attrs[name],
13898N/A anim = (attr) ? attr.transition : null,
13898N/A data,
13898N/A config;
13898N/A
15536N/A if (anim) {
15536N/A anim.removeProperty(name);
15536N/A anim._endNative(name);
16617N/A config = anim._config[name];
16617N/A
16617N/A data = {
16617N/A type: 'propertyEnd',
16617N/A propertyName: name,
16617N/A elapsedTime: elapsed,
16617N/A config: config
16617N/A };
16617N/A
16617N/A if (config && config.on && config.on.end) {
16617N/A config.on.end.call(Y.one(node), data);
15536N/A }
14376N/A
13898N/A //node.fire('transition:propertyEnd', data);
13898N/A
14376N/A if (anim._count <= 0) { // after propertyEnd fires
13898N/A anim._end(elapsed);
10550N/A }
10550N/A }
15536N/A },
10550N/A
15453N/A destroy: function() {
15453N/A var anim = this;
15453N/A /*
15453N/A if (anim._detach) {
10139N/A anim._detach.detach();
10139N/A }
10139N/A */
10139N/A //anim._node[ON_TRANSITION_END] = null;
10139N/A node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
10139N/A anim._node = null;
10139N/A }
10139N/A};
10139N/A
10139N/AY.Transition = Transition;
10139N/AY.TransitionNative = Transition; // TODO: remove
10139N/A
10139N/A/**
10139N/A * Animate one or more css properties to a given value. Requires the "transition" module.
10139N/A * <pre>example usage:
10139N/A * Y.one('#demo').transition({
10139N/A * duration: 1, // in seconds, default is 0.5
10139N/A * easing: 'ease-out', // default is 'ease'
10139N/A * delay: '1', // delay start for 1 second, default is 0
10139N/A *
10139N/A * height: '10px',
10139N/A * width: '10px',
10139N/A *
10139N/A * opacity: { // per property
10139N/A * value: 0,
10139N/A * duration: 2,
10139N/A * delay: 2,
10139N/A * easing: 'ease-in'
16952N/A * }
16952N/A * });
16952N/A * </pre>
16916N/A * @for Node
16916N/A * @method transition
16801N/A * @param {Object} config An object containing one or more style properties, a duration and an easing.
16801N/A * @param {Function} callback A function to run after the transition has completed.
16795N/A * @chainable
16795N/A*/
16795N/AY.Node.prototype.transition = function(name, config, callback) {
16794N/A var
16794N/A transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
16766N/A anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
16766N/A fxConfig,
16758N/A prop;
16758N/A
16732N/A if (typeof name === 'string') { // named effect, pull config from registry
16732N/A if (typeof config === 'function') {
16712N/A callback = config;
16712N/A config = null;
16702N/A }
16702N/A
16689N/A fxConfig = Transition.fx[name];
16689N/A
16680N/A if (config && typeof config !== 'boolean') {
16680N/A config = Y.clone(config);
16656N/A
16656N/A for (prop in fxConfig) {
16656N/A if (fxConfig.hasOwnProperty(prop)) {
16643N/A if (! (prop in config)) {
16643N/A config[prop] = fxConfig[prop];
16639N/A }
16639N/A }
16608N/A }
16617N/A } else {
16617N/A config = fxConfig;
16608N/A }
16608N/A
16601N/A } else { // name is a config, config is a callback or undefined
16553N/A callback = config;
16554N/A config = name;
16554N/A }
16554N/A
16554N/A if (anim && !anim._running) {
16553N/A anim.init(this, config);
16549N/A } else {
16549N/A anim = new Transition(this._node, config);
16549N/A }
16549N/A
16437N/A anim.run(callback);
16437N/A return this;
16437N/A};
16283N/A
16283N/AY.Node.prototype.show = function(name, config, callback) {
16283N/A this._show(); // show prior to transition
16279N/A if (name && Y.Transition) {
16279N/A if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
16279N/A if (typeof config === 'function') {
16207N/A callback = config;
16207N/A config = name;
16061N/A }
16061N/A name = this.SHOW_TRANSITION;
16050N/A }
16050N/A this.transition(name, config, callback);
16020N/A }
16020N/A else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); }
15902N/A return this;
15902N/A};
15797N/A
15797N/Avar _wrapCallBack = function(anim, fn, callback) {
15761N/A return function() {
15761N/A if (fn) {
15747N/A fn.call(anim);
15747N/A }
15606N/A if (callback) {
15606N/A callback.apply(anim._node, arguments);
15606N/A }
15548N/A };
15548N/A};
15548N/A
15536N/AY.Node.prototype.hide = function(name, config, callback) {
15536N/A if (name && Y.Transition) {
15535N/A if (typeof config === 'function') {
15535N/A callback = config;
15529N/A config = null;
15536N/A }
15529N/A
15529N/A callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
15529N/A if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
15525N/A if (typeof config === 'function') {
15536N/A callback = config;
15529N/A config = name;
15529N/A }
15529N/A name = this.HIDE_TRANSITION;
15529N/A }
15529N/A this.transition(name, config, callback);
15525N/A } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node'); // end if on nex
15516N/A } else {
15516N/A this._hide();
15516N/A }
15516N/A return this;
15516N/A};
15516N/A
15516N/A/**
15516N/A * Animate one or more css properties to a given value. Requires the "transition" module.
15516N/A * <pre>example usage:
15516N/A * Y.all('.demo').transition({
15516N/A * duration: 1, // in seconds, default is 0.5
15516N/A * easing: 'ease-out', // default is 'ease'
15516N/A * delay: '1', // delay start for 1 second, default is 0
15516N/A *
15516N/A * height: '10px',
15516N/A * width: '10px',
15516N/A *
15453N/A * opacity: { // per property
15453N/A * value: 0,
15453N/A * duration: 2,
15453N/A * delay: 2,
15418N/A * easing: 'ease-in'
15418N/A * }
15418N/A * });
15365N/A * </pre>
15365N/A * @for NodeList
15216N/A * @method transition
15216N/A * @param {Object} config An object containing one or more style properties, a duration and an easing.
15190N/A * @param {Function} callback A function to run after the transition has completed. The callback fires
15191N/A * once per item in the NodeList.
15191N/A * @chainable
15190N/A*/
15190N/AY.NodeList.prototype.transition = function(config, callback) {
15190N/A var nodes = this._nodes,
15190N/A i = 0,
15189N/A node;
15189N/A
14526N/A while ((node = nodes[i++])) {
14526N/A Y.one(node).transition(config, callback);
14526N/A }
14425N/A
14425N/A return this;
14425N/A};
14376N/A
14376N/AY.Node.prototype.toggleView = function(name, on, callback) {
14376N/A this._toggles = this._toggles || [];
14376N/A callback = arguments[arguments.length - 1];
14376N/A
14376N/A if (typeof name == 'boolean') { // no transition, just toggle
14376N/A on = name;
14190N/A name = null;
14190N/A }
14124N/A
14124N/A name = name || Y.Transition.DEFAULT_TOGGLE;
14099N/A
14099N/A if (typeof on == 'undefined' && name in this._toggles) { // reverse current toggle
14033N/A on = ! this._toggles[name];
14033N/A }
14033N/A
13996N/A on = (on) ? 1 : 0;
13926N/A if (on) {
13926N/A this._show();
13914N/A } else {
13914N/A callback = _wrapCallBack(this, this._hide, callback);
13914N/A }
13914N/A
13914N/A this._toggles[name] = on;
13898N/A this.transition(Y.Transition.toggles[name][on], callback);
13898N/A
13898N/A return this;
13898N/A};
13898N/A
13898N/AY.NodeList.prototype.toggleView = function(name, on, callback) {
13898N/A var nodes = this._nodes,
13898N/A i = 0,
13898N/A node;
13600N/A
13600N/A while ((node = nodes[i++])) {
13898N/A Y.one(node).toggleView(name, on, callback);
13898N/A }
13898N/A
13898N/A return this;
13577N/A};
13898N/A
13898N/AY.mix(Transition.fx, {
13898N/A fadeOut: {
13898N/A opacity: 0,
13898N/A duration: 0.5,
13898N/A easing: 'ease-out'
13898N/A },
13898N/A
13898N/A fadeIn: {
13898N/A opacity: 1,
13898N/A duration: 0.5,
13898N/A easing: 'ease-in'
13898N/A },
13898N/A
13898N/A sizeOut: {
13898N/A height: 0,
13268N/A width: 0,
13268N/A duration: 0.75,
13268N/A easing: 'ease-out'
13898N/A },
13898N/A
13898N/A sizeIn: {
13898N/A height: function(node) {
13898N/A return node.get('scrollHeight') + 'px';
13898N/A },
13898N/A width: function(node) {
13898N/A return node.get('scrollWidth') + 'px';
13898N/A },
12830N/A duration: 0.5,
13898N/A easing: 'ease-in',
12830N/A
13898N/A on: {
13898N/A start: function() {
13898N/A var overflow = this.getStyle('overflow');
13898N/A if (overflow !== 'hidden') { // enable scrollHeight/Width
13898N/A this.setStyle('overflow', 'hidden');
13898N/A this._transitionOverflow = overflow;
13898N/A }
13898N/A },
13898N/A
12169N/A end: function() {
13898N/A if (this._transitionOverflow) { // revert overridden value
12169N/A this.setStyle('overflow', this._transitionOverflow);
12169N/A }
12102N/A }
12102N/A }
12097N/A }
12097N/A});
12097N/A
12018N/AY.mix(Transition.toggles, {
12018N/A size: ['sizeOut', 'sizeIn'],
11999N/A fade: ['fadeOut', 'fadeIn']
11999N/A});
11999N/A
11996N/ATransition.DEFAULT_TOGGLE = 'fade';
11996N/A
11908N/A
11910N/A
11910N/A}, '@VERSION@' ,{requires:['node-base']});
11854N/AYUI.add('transition-timer', function(Y) {
11854N/A
11440N/A/*
11440N/A* The Transition Utility provides an API for creating advanced transitions.
11425N/A* @module transition
11425N/A*/
11314N/A
11314N/A/*
11280N/A* Provides the base Transition class, for animating numeric properties.
11280N/A*
11004N/A* @module transition
11004N/A* @submodule transition-timer
10946N/A*/
10946N/A
10946N/A
10844N/Avar Transition = Y.Transition;
10844N/A
10844N/AY.mix(Transition.prototype, {
10711N/A _start: function() {
10711N/A if (Transition.useNative) {
10685N/A this._runNative();
10685N/A } else {
10550N/A this._runTimer();
10550N/A }
10544N/A },
10544N/A
10465N/A _runTimer: function() {
10465N/A var anim = this;
10465N/A anim._initAttrs();
10447N/A
10447N/A Transition._running[Y.stamp(anim)] = anim;
10404N/A anim._startTime = new Date();
10404N/A Transition._startTimer();
10340N/A },
10340N/A
10330N/A _endTimer: function() {
10330N/A var anim = this;
10330N/A delete Transition._running[Y.stamp(anim)];
10330N/A anim._startTime = null;
10330N/A },
10161N/A
10161N/A _runFrame: function() {
10161N/A var t = new Date() - this._startTime;
10139N/A this._runAttrs(t);
10139N/A },
10139N/A
10139N/A _runAttrs: function(time) {
10139N/A var anim = this,
10139N/A node = anim._node,
10139N/A config = anim._config,
10139N/A uid = Y.stamp(node),
10139N/A attrs = Transition._nodeAttrs[uid],
10139N/A customAttr = Transition.behaviors,
10139N/A done = false,
10139N/A allDone = false,
10139N/A data,
10139N/A name,
10139N/A attribute,
10139N/A setter,
10139N/A elapsed,
10139N/A delay,
10139N/A d,
10139N/A t,
10139N/A i;
10139N/A
10139N/A for (name in attrs) {
10139N/A attribute = attrs[name];
10139N/A if ((attribute && attribute.transition === anim)) {
10139N/A d = attribute.duration;
10139N/A delay = attribute.delay;
10139N/A elapsed = (time - delay) / 1000;
10139N/A t = time;
10139N/A data = {
10139N/A type: 'propertyEnd',
10139N/A propertyName: name,
10139N/A config: config,
10139N/A elapsedTime: elapsed
10139N/A };
10139N/A
10139N/A setter = (i in customAttr && 'set' in customAttr[i]) ?
10139N/A customAttr[i].set : Transition.DEFAULT_SETTER;
10139N/A
10139N/A done = (t >= d);
10139N/A
10139N/A if (t > d) {
10139N/A t = d;
10139N/A }
10139N/A
10139N/A if (!delay || time >= delay) {
10139N/A setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
10139N/A attribute.easing, attribute.unit);
10139N/A
10139N/A if (done) {
10139N/A delete attrs[name];
10139N/A anim._count--;
10139N/A
10139N/A if (config[name] && config[name].on && config[name].on.end) {
10139N/A config[name].on.end.call(Y.one(node), data);
10139N/A }
10139N/A
10139N/A //node.fire('transition:propertyEnd', data);
10139N/A
10139N/A if (!allDone && anim._count <= 0) {
10139N/A allDone = true;
10139N/A anim._end(elapsed);
10139N/A anim._endTimer();
10139N/A }
10139N/A }
10139N/A }
10139N/A
10139N/A }
10139N/A }
10139N/A },
10139N/A
10139N/A _initAttrs: function() {
10139N/A var anim = this,
10139N/A customAttr = Transition.behaviors,
10139N/A uid = Y.stamp(anim._node),
10139N/A attrs = Transition._nodeAttrs[uid],
10139N/A attribute,
10139N/A duration,
10139N/A delay,
10139N/A easing,
10139N/A val,
10139N/A name,
10139N/A mTo,
10139N/A mFrom,
10139N/A unit, begin, end;
10139N/A
10139N/A for (name in attrs) {
10139N/A attribute = attrs[name];
10139N/A if (attrs.hasOwnProperty(name) && (attribute && attribute.transition === anim)) {
10139N/A duration = attribute.duration * 1000;
10139N/A delay = attribute.delay * 1000;
10139N/A easing = attribute.easing;
10139N/A val = attribute.value;
10139N/A
10139N/A // only allow supported properties
10139N/A if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
10139N/A begin = (name in customAttr && 'get' in customAttr[name]) ?
10139N/A customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
10139N/A
10139N/A mFrom = Transition.RE_UNITS.exec(begin);
10139N/A mTo = Transition.RE_UNITS.exec(val);
10139N/A
10139N/A begin = mFrom ? mFrom[1] : begin;
10139N/A end = mTo ? mTo[1] : val;
10139N/A unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units
10139N/A
10139N/A if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
10139N/A unit = Transition.DEFAULT_UNIT;
10139N/A }
10139N/A
10139N/A if (typeof easing === 'string') {
10139N/A if (easing.indexOf('cubic-bezier') > -1) {
10139N/A easing = easing.substring(13, easing.length - 1).split(',');
10139N/A } else if (Transition.easings[easing]) {
10139N/A easing = Transition.easings[easing];
10139N/A }
10139N/A }
11314N/A
11314N/A attribute.from = Number(begin);
11314N/A attribute.to = Number(end);
10139N/A attribute.unit = unit;
10139N/A attribute.easing = easing;
10139N/A attribute.duration = duration + delay;
10139N/A attribute.delay = delay;
10139N/A } else {
10139N/A delete attrs[name];
10139N/A anim._count--;
10139N/A }
10139N/A }
10139N/A }
10139N/A },
10139N/A
10139N/A destroy: function() {
10139N/A this.detachAll();
10139N/A this._node = null;
10139N/A }
10139N/A}, true);
10139N/A
10139N/AY.mix(Y.Transition, {
10139N/A _runtimeAttrs: {},
10139N/A /*
* Regex of properties that should use the default unit.
*
* @property RE_DEFAULT_UNIT
* @static
*/
RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
/*
* The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
*
* @property DEFAULT_UNIT
* @static
*/
DEFAULT_UNIT: 'px',
/*
* Time in milliseconds passed to setInterval for frame processing
*
* @property intervalTime
* @default 20
* @static
*/
intervalTime: 20,
/*
* Bucket for custom getters and setters
*
* @property behaviors
* @static
*/
behaviors: {
left: {
get: function(anim, attr) {
return Y.DOM._getAttrOffset(anim._node, attr);
}
}
},
/*
* The default setter to use when setting object properties.
*
* @property DEFAULT_SETTER
* @static
*/
DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
from = Number(from);
to = Number(to);
var node = anim._node,
val = Transition.cubicBezier(fn, elapsed / duration);
val = from + val[0] * (to - from);
if (node) {
if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
unit = unit || '';
Y.DOM.setStyle(node, att, val + unit);
}
} else {
anim._end();
}
},
/*
* The default getter to use when getting object properties.
*
* @property DEFAULT_GETTER
* @static
*/
DEFAULT_GETTER: function(anim, att) {
var node = anim._node,
val = '';
if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
val = Y.DOM.getComputedStyle(node, att);
}
return val;
},
_startTimer: function() {
if (!Transition._timer) {
Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
}
},
_stopTimer: function() {
clearInterval(Transition._timer);
Transition._timer = null;
},
/*
* Called per Interval to handle each animation frame.
* @method _runFrame
* @private
* @static
*/
_runFrame: function() {
var done = true,
anim;
for (anim in Transition._running) {
if (Transition._running[anim]._runFrame) {
done = false;
Transition._running[anim]._runFrame();
}
}
if (done) {
Transition._stopTimer();
}
},
cubicBezier: function(p, t) {
var x0 = 0,
y0 = 0,
x1 = p[0],
y1 = p[1],
x2 = p[2],
y2 = p[3],
x3 = 1,
y3 = 0,
A = x3 - 3 * x2 + 3 * x1 - x0,
B = 3 * x2 - 6 * x1 + 3 * x0,
C = 3 * x1 - 3 * x0,
D = x0,
E = y3 - 3 * y2 + 3 * y1 - y0,
F = 3 * y2 - 6 * y1 + 3 * y0,
G = 3 * y1 - 3 * y0,
H = y0,
x = (((A*t) + B)*t + C)*t + D,
y = (((E*t) + F)*t + G)*t + H;
return [x, y];
},
easings: {
ease: [0.25, 0, 1, 0.25],
linear: [0, 0, 1, 1],
'ease-in': [0.42, 0, 1, 1],
'ease-out': [0, 0, 0.58, 1],
'ease-in-out': [0.42, 0, 0.58, 1]
},
_running: {},
_timer: null,
RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
}, true);
Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
Y.Transition = Transition;
}, '@VERSION@' ,{requires:['transition-native', 'node-style']});
YUI.add('transition', function(Y){}, '@VERSION@' ,{use:['transition-native', 'transition-timer']});