mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
feat(ngAnimate): provide configuration support to match specific className values to trigger animations
Closes #5357 Closes #5283
This commit is contained in:
parent
937caab647
commit
cef084ade9
3 changed files with 86 additions and 4 deletions
|
|
@ -61,6 +61,28 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|||
$provide.factory(key, factory);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name ng.$animateProvider#classNameFilter
|
||||
* @methodOf ng.$animateProvider
|
||||
*
|
||||
* @description
|
||||
* Sets and/or returns the CSS class regular expression that is checked when performing
|
||||
* an animation. Upon bootstrap the classNameFilter value is not set at all and will
|
||||
* therefore enable $animate to attempt to perform an animation on any element.
|
||||
* When setting the classNameFilter value, animations will only be performed on elements
|
||||
* that successfully match the filter expression. This in turn can boost performance
|
||||
* for low-powered devices as well as applications containing a lot of structural operations.
|
||||
* @param {RegExp=} expression The className expression which will be checked against all animations
|
||||
* @return {RegExp} The current CSS className expression value. If null then there is no expression value
|
||||
*/
|
||||
this.classNameFilter = function(expression) {
|
||||
if(arguments.length === 1) {
|
||||
this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
|
||||
}
|
||||
return this.$$classNameFilter;
|
||||
};
|
||||
|
||||
this.$get = ['$timeout', function($timeout) {
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -288,6 +288,13 @@ angular.module('ngAnimate', ['ng'])
|
|||
});
|
||||
});
|
||||
|
||||
var classNameFilter = $animateProvider.classNameFilter();
|
||||
var isAnimatableClassName = !classNameFilter
|
||||
? function() { return true; }
|
||||
: function(className) {
|
||||
return classNameFilter.test(className);
|
||||
};
|
||||
|
||||
function lookup(name) {
|
||||
if (name) {
|
||||
var matches = [],
|
||||
|
|
@ -569,17 +576,20 @@ angular.module('ngAnimate', ['ng'])
|
|||
and the onComplete callback will be fired once the animation is fully complete.
|
||||
*/
|
||||
function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) {
|
||||
var node = extractElementNode(element);
|
||||
var currentClassName, classes, node = extractElementNode(element);
|
||||
if(node) {
|
||||
currentClassName = node.className;
|
||||
classes = currentClassName + ' ' + className;
|
||||
}
|
||||
|
||||
//transcluded directives may sometimes fire an animation using only comment nodes
|
||||
//best to catch this early on to prevent any animation operations from occurring
|
||||
if(!node) {
|
||||
if(!node || !isAnimatableClassName(classes)) {
|
||||
fireDOMOperation();
|
||||
closeAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentClassName = node.className;
|
||||
var classes = currentClassName + ' ' + className;
|
||||
var animationLookup = (' ' + classes).replace(/\s+/g,'.');
|
||||
if (!parentElement) {
|
||||
parentElement = afterElement ? afterElement.parent() : element.parent();
|
||||
|
|
|
|||
|
|
@ -2947,5 +2947,55 @@ describe("ngAnimate", function() {
|
|||
expect(capturedAnimation).toBe('leave');
|
||||
});
|
||||
});
|
||||
|
||||
it('should animate only the specified CSS className', function() {
|
||||
var captures = {};
|
||||
module(function($animateProvider) {
|
||||
$animateProvider.classNameFilter(/prefixed-animation/);
|
||||
$animateProvider.register('.capture', function() {
|
||||
return {
|
||||
enter : buildFn('enter'),
|
||||
leave : buildFn('leave')
|
||||
};
|
||||
|
||||
function buildFn(key) {
|
||||
return function(element, className, done) {
|
||||
captures[key] = true;
|
||||
(done || className)();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
inject(function($rootScope, $compile, $rootElement, $document, $timeout, $templateCache, $sniffer, $animate) {
|
||||
if(!$sniffer.transitions) return;
|
||||
|
||||
var element = $compile('<div class="capture"></div>')($rootScope);
|
||||
$rootElement.append(element);
|
||||
jqLite($document[0].body).append($rootElement);
|
||||
|
||||
var enterDone = false;
|
||||
$animate.enter(element, $rootElement, null, function() {
|
||||
enterDone = true;
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
expect(captures['enter']).toBeUndefined();
|
||||
expect(enterDone).toBe(true);
|
||||
|
||||
element.addClass('prefixed-animation');
|
||||
|
||||
var leaveDone = false;
|
||||
$animate.leave(element, function() {
|
||||
leaveDone = true;
|
||||
});
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
expect(captures['leave']).toBe(true);
|
||||
expect(leaveDone).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue