213 lines
7.9 KiB
JavaScript
213 lines
7.9 KiB
JavaScript
|
/*
|
|||
|
* 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`.
|
|||
|
// It’s 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 didn’t 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 doesn’t 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 won’t 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);
|