Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

feat($animate): proper support for multiple elements #5570

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 70 additions & 26 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ angular.module('ngAnimate', ['ng'])
cancelChildAnimations(element);
this.enabled(false, element);
$rootScope.$$postDigest(function() {
performAnimation('leave', 'ng-leave', element, null, null, function() {
performAnimation('leave', 'ng-leave', element, null, null, function(element) {
$delegate.leave(element);
}, doneCallback);
});
Expand Down Expand Up @@ -515,7 +515,7 @@ angular.module('ngAnimate', ['ng'])
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
*/
addClass : function(element, className, doneCallback) {
performAnimation('addClass', className, element, null, null, function() {
performAnimation('addClass', className, element, null, null, function(element) {
$delegate.addClass(element, className);
}, doneCallback);
},
Expand Down Expand Up @@ -551,7 +551,7 @@ angular.module('ngAnimate', ['ng'])
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
*/
removeClass : function(element, className, doneCallback) {
performAnimation('removeClass', className, element, null, null, function() {
performAnimation('removeClass', className, element, null, null, function(element) {
$delegate.removeClass(element, className);
}, doneCallback);
},
Expand All @@ -570,15 +570,21 @@ angular.module('ngAnimate', ['ng'])
* Globally enables/disables animations.
*
*/
enabled : function(value, element) {
enabled : function(value, contents) {
switch(arguments.length) {
case 2:
if(value) {
cleanup(element);
} else {
var data = element.data(NG_ANIMATE_STATE) || {};
data.disabled = true;
element.data(NG_ANIMATE_STATE, data);
var content, data;
for (var i = 0; i < contents.length; i++) {
content = angular.element(contents[i]);
if(content[0].nodeType == ELEMENT_NODE) {
if(value) {
cleanup(content);
} else {
data = content.data(NG_ANIMATE_STATE) || {};
data.disabled = true;
content.data(NG_ANIMATE_STATE, data);
}
}
}
break;

Expand All @@ -601,16 +607,49 @@ angular.module('ngAnimate', ['ng'])
CSS code. Element, parentElement and afterElement are provided DOM elements for the animation
and the onComplete callback will be fired once the animation is fully complete.
*/
function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) {
var currentClassName, classes, node = extractElementNode(element);
if(node) {
currentClassName = node.className;
classes = currentClassName + ' ' + className;
function performAnimation(animationEvent, className, contents, parentElement, afterElement, domOperation, doneCallback) {

var i, elementsCount = 0, content;

var args = Array.prototype.slice.call(arguments, 0);

args[6] = subElmDone;

for (i = 0; i < contents.length; i++) {
content = args[2] = angular.element(contents[i]);
if(content[0].nodeType == ELEMENT_NODE) {
elementsCount++;
// jshint -W040
performAnimationForElement.apply(this, args);
} else if (domOperation) {
// Fire DOM operation straightaway
domOperation(content);
}
}

if (!elementsCount) {
doneCallback && $timeout(doneCallback, 0, false);
}

function subElmDone() {
// This method is always invoked asynchronously
if (++subElmDone.doneCount == elementsCount) {
doneCallback && doneCallback();
}
}

subElmDone.doneCount = 0;

}

function performAnimationForElement(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) {
var node = element[0],
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 || !isAnimatableClassName(classes)) {
if(!isAnimatableClassName(classes)) {
fireDOMOperation();
fireBeforeCallbackAsync();
fireAfterCallbackAsync();
Expand Down Expand Up @@ -838,7 +877,7 @@ angular.module('ngAnimate', ['ng'])
function fireDOMOperation() {
if(!fireDOMOperation.hasBeenRun) {
fireDOMOperation.hasBeenRun = true;
domOperation();
domOperation(element);
}
}

Expand All @@ -865,16 +904,21 @@ angular.module('ngAnimate', ['ng'])
}
}

function cancelChildAnimations(element) {
var node = extractElementNode(element);
forEach(node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME), function(element) {
element = angular.element(element);
var data = element.data(NG_ANIMATE_STATE);
if(data) {
cancelAnimations(data.animations);
cleanup(element);
function cancelChildAnimations(contents) {
var node;
for (var i = 0; i < contents.length; i++) {
node = contents[i];
if (node.nodeType == ELEMENT_NODE) {
forEach(node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME), function(element) {
element = angular.element(element);
var data = element.data(NG_ANIMATE_STATE);
if(data) {
cancelAnimations(data.animations);
cleanup(element);
}
});
}
});
}
}

function cancelAnimations(animations) {
Expand Down
Loading