social-likes-nojq/gh-pages/tamia/vendor/transition-events.js

213 lines
7.9 KiB
JavaScript
Raw Normal View History

/*
* Copyright 2012 Andrey A.I. Sitnik <andrey@sitnik.ru>,
* sponsored by Evil Martians.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
;(function($) {
"use strict";
// Common methods and properties for jQuery Transition Events plugin.
// Mostly for internal usage, but maybe helpful for some hack stuff:
//
// if ( $.Transitions.isSupported() ) {
// // CSS Transitions is supported
// }
$.Transitions = {
// Hash of property name to event name with vendor prefixes.
// It is used to detect prefix.
_names: {
// Webkit must be on bottom, because Opera try to use webkit
// prefix.
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend'
},
// Return array of milliseconds for CSS value of `transition-duration`.
// Its used in `$.fn.afterTransition`.
_parseTimes: function (string) {
var value, array = string.split(/,\s*/);
for (var i = 0; i < array.length; i++) {
value = array[i];
array[i] = parseFloat(value);
if ( value.match(/\ds/) ) {
array[i] = array[i] * 1000;
}
}
return array;
},
// Autodetect vendor prefix and return `transitionend` event name.
//
// If browser didnt support CSS Transitions it will return `false`.
getEvent: function () {
var finded = false;
for ( var prop in this._names ) {
if ( typeof(document.body.style[prop]) != 'undefined' ) {
finded = this._names[prop];
break;
}
}
this.getEvent = function () {
return finded;
};
return finded;
},
// Alias to vendor prefixed `requestAnimationFrame`. Will be replace
// by native function after first call.
animFrame: function (callback) {
var raf = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame;
if ( raf ) {
this.animFrame = function (callback) {
return raf.call(window, callback);
};
} else {
this.animFrame = function (callback) {
return setTimeout(callback, 10);
};
}
return this.animFrame(callback);
},
// Return `true` if browser support CSS Transitions.
isSupported: function () {
return this.getEvent() !== false;
}
}
// jQuery node methods.
$.extend($.fn, {
// Call `callback` after CSS Transition finish
// `delay + (durationPart * duration)`. It will call `callback` only
// once, in difference from `transitionEnd`.
//
// $('.show-video').click(function () {
// $('.slider').addClass('video-position').afterTransition(
// function () { autoPlayVideo(); });
// });
//
// You can set `durationPart` to call `callback` in the middle of
// transition:
//
// $('.fliper').addClass('rotate').afterTransition(0.5, function () {
// $(this).find('.backface').show();
// });
//
// Callback will get object with `propertyName` and `elapsedTime`
// properties. If transition is set to difference properties, it will
// be called on every property.
//
// This method doesnt check, that transition is really finished (it can
// be canceled in the middle).
afterTransition: function (durationPart, callback) {
if ( typeof(callback) == 'undefined' ) {
callback = durationPart;
durationPart = 1;
}
if ( !$.Transitions.isSupported() ) {
for (var i = 0; i < this.length; i++) {
callback.call(this[i], {
type: 'aftertransition',
elapsedTime: 0,
propertyName: '',
currentTarget: this[i]
});
}
return this;
}
for (var i = 0; i < this.length; i++) {
var el = $(this[i]);
var props = el.css('transition-property').split(/,\s*/);
var durations = el.css('transition-duration');
var delays = el.css('transition-delay');
durations = $.Transitions._parseTimes(durations);
delays = $.Transitions._parseTimes(delays);
var prop, duration, delay, after, elapsed;
for (var j = 0; j < props.length; j++) {
prop = props[j];
duration = durations[ durations.length == 1 ? 0 : j ];
delay = delays[ delays.length == 1 ? 0 : j ];
after = delay + (duration * durationPart);
elapsed = duration * durationPart / 1000;
(function (el, prop, after, elapsed) {
setTimeout(function () {
$.Transitions.animFrame(function () {
callback.call(el[0], {
type: 'aftertransition',
elapsedTime: elapsed,
propertyName: prop,
currentTarget: el[0]
});
});
}, after);
})(el, prop, after, elapsed);
}
}
return this;
},
// Set `callback` to listen every CSS Transition finish.
// It will call `callback` on every finished transition,
// in difference from `afterTransition`.
//
// It just bind to `transitionend` event, but detect vendor prefix.
//
// Callback will get event object with `propertyName` and `elapsedTime`
// properties. If transition is set to difference properties, it will
// be called on every property.
//
// Note, that `callback` will get original event object, not from
// jQuery.
//
// var slider = $('.slider').transitionEnd(function () {
// if ( slider.hasClass('video-position') ) {
// autoPlayVideo();
// }
// });
//
// $('.show-video').click(function () {
// slider.addClass('video-position');
// });
//
// If transition will be canceled before finish, event wont be fired.
transitionEnd: function (callback) {
for (var i = 0; i < this.length; i++) {
this[i].addEventListener($.Transitions.getEvent(), function (e) {
callback.call(this, e);
});
}
return this;
}
});
}).call(this, jQuery);