transition-debug.js revision 07fb5348687ec773fa272861805537c14a1c5c5c
9c94a3bab3da130a453194d151f33f11cd53f44eMatt Sweeney* Provides the transition method for Node.
4527b08ced97d1bf5f88cf786302fd66eb80a35bMatt Sweeney* Transition has no API of its own, but adds the transition method to Node.
60dcf3ebba038d9ec57d617a7395a9bff15802fcMatt Sweeney* @module transition
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney* @requires node-style
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * A class for constructing transition instances.
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * Adds the "transition" method to Node.
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * @class Transition
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * @constructor
f01d121976553130cab6089d35c71d5b947d1204Matt Sweeney property = property.replace(/-([a-z])/gi, function(m0, m1) {
bf3c648d6ab588c8b04fb824a7281898c469bd67Matt Sweeney property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
416ff6e8477a5950c56e04adea6abf838140a852Matt Sweeney var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyY.Array.each(VENDORS, function(val) { // then vendor specific
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney VENDOR_PREFIX = Transition._toHyphen(val) + '-';
416ff6e8477a5950c56e04adea6abf838140a852Matt SweeneyTRANSITION_CAMEL = CAMEL_VENDOR_PREFIX + TRANSITION_CAMEL;
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_PROPERTY = VENDOR_PREFIX + 'transition-property';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_DURATION = VENDOR_PREFIX + 'transition-duration';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_DELAY = VENDOR_PREFIX + 'transition-delay';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSITION_END = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTRANSFORM_CAMEL = CAMEL_VENDOR_PREFIX + 'Transform';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt SweeneyTransition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
576e5aadaa60b824ce0a3875d3551ca3151a1957Matt Sweeney config.duration: anim.constructor.DEFAULT_DURATION;
576e5aadaa60b824ce0a3875d3551ca3151a1957Matt Sweeney anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
576e5aadaa60b824ce0a3875d3551ca3151a1957Matt Sweeney anim._count = 0; // track number of animated properties
100cd7da99ccec416d3021e9a567addc2d9ed3dfMatt Sweeney // might just be a value
142b1eb4e6b33c96ecf163bf42d31147b2e0e1d0Matt Sweeney // take control if another transition owns this property
142b1eb4e6b33c96ecf163bf42d31147b2e0e1d0Matt Sweeney attr.transition._count--; // remapping attr to this transition
0df23d09dc16bc41af5ceff68c11ed9c7d6285edMatt Sweeney // make 0 async and fire events
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney dur = ((typeof config.duration != 'undefined') ? config.duration :
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney delay: (typeof config.delay != 'undefined') ? config.delay :
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney // native end event doesnt fire when setting to same value
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney // supplementing with timer
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney // val may be a string or number (height: 0, etc), but computedStyle is always string
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
5985d0db35cae8ef4c1a022bb03ac15792ff51adMatt Sweeney if (Transition.useNative && compareVal === val) {
100cd7da99ccec416d3021e9a567addc2d9ed3dfMatt Sweeney attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
100cd7da99ccec416d3021e9a567addc2d9ed3dfMatt Sweeney if (config.transform && !config[TRANSFORM_CAMEL]) {
100cd7da99ccec416d3021e9a567addc2d9ed3dfMatt Sweeney if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
ac08645fa535c4f48d2fa888fee02423ff9afe17Matt Sweeney // when size is auto or % webkit starts from zero instead of computed
ac08645fa535c4f48d2fa888fee02423ff9afe17Matt Sweeney // (https://bugs.webkit.org/show_bug.cgi?id=16020)
ac08645fa535c4f48d2fa888fee02423ff9afe17Matt Sweeney // TODO: selective set
ac08645fa535c4f48d2fa888fee02423ff9afe17Matt Sweeney Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney * Starts or an animation.
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney * @method run
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney * @chainable
3f4cbe6edb218980892f798d09f41c804aeaa301Matt Sweeney //anim._node.fire('transition:start', data);
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney _start: function() {
07fb5348687ec773fa272861805537c14a1c5c5cMatt Sweeney computed = node.ownerDocument.defaultView.getComputedStyle(node),
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
448834d88f7c2818b5a70125bba193051806ccf9Matt Sweeney // preserve existing transitions
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
448834d88f7c2818b5a70125bba193051806ccf9Matt Sweeney // run transitions mapped to this instance
416ff6e8477a5950c56e04adea6abf838140a852Matt Sweeney if ((attr = attrs[name]) && attr.transition === anim) {
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney if (name in node.style) { // only native styles allowed
f01d121976553130cab6089d35c71d5b947d1204Matt Sweeney duration += anim._prepDur(attr.duration) + ',';
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney transitionText = transitionText.replace(/,$/, ';');
448834d88f7c2818b5a70125bba193051806ccf9Matt Sweeney // only one native end event per node
564c5c8d77e1fe074bfa96133bfdbbd0707c1ed3Matt Sweeney //anim._detach = Y.on(TRANSITION_END, anim._onNativeEnd, node);
564c5c8d77e1fe074bfa96133bfdbbd0707c1ed3Matt Sweeney //node[ON_TRANSITION_END] = anim._onNativeEnd;
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
142b1eb4e6b33c96ecf163bf42d31147b2e0e1d0Matt Sweeney //setTimeout(function() { // allow updates to apply (size fix, onstart, etc)
142b1eb4e6b33c96ecf163bf42d31147b2e0e1d0Matt Sweeney style.cssText += transitionText + duration + easing + delay + cssText;
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney setTimeout(function() { // IE: allow previous update to finish
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney // nested to ensure proper fire order
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney } else if (callback) {
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney setTimeout(function() { // IE: allow previous update to finish
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney //node.fire('transition:end', data);
2e49faa8717cc2acbd7ab2aac237061848568a6cMatt Sweeney value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
100cd7da99ccec416d3021e9a567addc2d9ed3dfMatt Sweeney value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney _onNativeEnd: function(e) {
f01d121976553130cab6089d35c71d5b947d1204Matt Sweeney name = Transition._toCamel(event.propertyName),
3f4cbe6edb218980892f798d09f41c804aeaa301Matt Sweeney //node.fire('transition:propertyEnd', data);
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney if (anim._count <= 0) { // after propertyEnd fires
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney destroy: function() {
6ae23e4adfd7a02fb24e8240a363e0decf126c95Matt Sweeney if (anim._detach) {
6ae23e4adfd7a02fb24e8240a363e0decf126c95Matt Sweeney anim._detach.detach();
564c5c8d77e1fe074bfa96133bfdbbd0707c1ed3Matt Sweeney //anim._node[ON_TRANSITION_END] = null;
416ff6e8477a5950c56e04adea6abf838140a852Matt Sweeney node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
959c053d56a076109993a2f14094d20b1f8c0c17Matt SweeneyY.TransitionNative = Transition; // TODO: remove
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * Animate one or more css properties to a given value. Requires the "transition" module.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * <pre>example usage:
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * Y.one('#demo').transition({
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * duration: 1, // in seconds, default is 0.5
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * easing: 'ease-out', // default is 'ease'
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * delay: '1', // delay start for 1 second, default is 0
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * height: '10px',
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * width: '10px',
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * opacity: { // per property
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * duration: 2,
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * easing: 'ease-in'
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @method transition
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @param {Object} config An object containing one or more style properties, a duration and an easing.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @param {Function} callback A function to run after the transition has completed.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @chainable
c56d37350cde9ba6fcde1a42433b3d759fe2b2ecMatt SweeneyY.Node.prototype.transition = function(name, config, callback) {
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
0512667d3ebce1dd2bac2bd1de6367420402cfb3Matt Sweeney anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
c56d37350cde9ba6fcde1a42433b3d759fe2b2ecMatt Sweeney if (typeof name === 'string') { // named effect, pull config from registry
c56d37350cde9ba6fcde1a42433b3d759fe2b2ecMatt Sweeney } else { // name is a config, config is a callback or undefined
959c053d56a076109993a2f14094d20b1f8c0c17Matt Sweeney return this;
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt SweeneyY.Node.prototype.show = function(name, config, callback) {
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); }
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney return this;
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeneyvar _wrapCallBack = function(anim, fn, callback) {
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney return function() {
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt SweeneyY.Node.prototype.hide = function(name, config, callback) {
b92e4372c5a34f48e457b60dfa9b136cf19c8498Matt Sweeney callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node'); // end if on nex
73857faca3d4266c7840cd6ce428a71cf9a94d0cMatt Sweeney return this;
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * Animate one or more css properties to a given value. Requires the "transition" module.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * <pre>example usage:
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * Y.all('.demo').transition({
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * duration: 1, // in seconds, default is 0.5
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * easing: 'ease-out', // default is 'ease'
ef982fe144b380cd6cd8dd1bc6ba74c7210033f9Matt Sweeney * delay: '1', // delay start for 1 second, default is 0
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * height: '10px',
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * width: '10px',
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * opacity: { // per property
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * duration: 2,
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * easing: 'ease-in'
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @for NodeList
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @method transition
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @param {Object} config An object containing one or more style properties, a duration and an easing.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @param {Function} callback A function to run after the transition has completed. The callback fires
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * once per item in the NodeList.
54329bf323458a34db1104ad4b4b0b1eaa1f12feMatt Sweeney * @chainable
a8592deb8f7e9124b473044326ef8cfadc4281d5Matt SweeneyY.NodeList.prototype.transition = function(config, callback) {
a8592deb8f7e9124b473044326ef8cfadc4281d5Matt Sweeney return this;
f0d88feb1b7e3a775e0e9c8648faf84a32250546Matt SweeneyY.Node.prototype.toggleView = function(name, on, callback) {
0512667d3ebce1dd2bac2bd1de6367420402cfb3Matt Sweeney if (typeof name == 'boolean') { // no transition, just toggle
20161237a86d2a737d4137221848801fdc54610fMatt Sweeney if (typeof on == 'undefined' && name in this._toggles) { // reverse current toggle
f0d88feb1b7e3a775e0e9c8648faf84a32250546Matt Sweeney callback = _wrapCallBack(this, this._hide, callback);
0512667d3ebce1dd2bac2bd1de6367420402cfb3Matt Sweeney this.transition(Y.Transition.toggles[name][on], callback);
7f03c81c9c42b32e09a911682e00adb57f0985b9Matt Sweeney return this;
20161237a86d2a737d4137221848801fdc54610fMatt SweeneyY.NodeList.prototype.toggleView = function(name, on, callback) {
0512667d3ebce1dd2bac2bd1de6367420402cfb3Matt Sweeney return this;
484ded111840f4104ab556e0628b0e84632eba34Matt Sweeney start: function() {
484ded111840f4104ab556e0628b0e84632eba34Matt Sweeney if (overflow !== 'hidden') { // enable scrollHeight/Width
484ded111840f4104ab556e0628b0e84632eba34Matt Sweeney end: function() {
484ded111840f4104ab556e0628b0e84632eba34Matt Sweeney if (this._transitionOverflow) { // revert overridden value
484ded111840f4104ab556e0628b0e84632eba34Matt Sweeney this.setStyle('overflow', this._transitionOverflow);