diff --git a/benchmarks/animation-bp/app.js b/benchmarks/animation-bp/app.js new file mode 100644 index 000000000000..82a4ca1dd8c9 --- /dev/null +++ b/benchmarks/animation-bp/app.js @@ -0,0 +1,44 @@ +'use strict'; + +angular + .module('animationBenchmark', ['ngAnimate'], config) + .controller('BenchmarkController', BenchmarkController); + +// Functions - Definitions +function config($compileProvider) { + $compileProvider + .commentDirectivesEnabled(false) + .cssClassDirectivesEnabled(false) + .debugInfoEnabled(false); +} + +function BenchmarkController($scope) { + var self = this; + var itemCount = 1000; + var items = (new Array(itemCount + 1)).join('.').split(''); + + benchmarkSteps.push({ + name: 'create', + fn: function() { + $scope.$apply(function() { + self.items = items; + }); + } + }); + + benchmarkSteps.push({ + name: '$digest', + fn: function() { + $scope.$root.$digest(); + } + }); + + benchmarkSteps.push({ + name: 'destroy', + fn: function() { + $scope.$apply(function() { + self.items = []; + }); + } + }); +} diff --git a/benchmarks/animation-bp/bp.conf.js b/benchmarks/animation-bp/bp.conf.js new file mode 100644 index 000000000000..535d6fd5d561 --- /dev/null +++ b/benchmarks/animation-bp/bp.conf.js @@ -0,0 +1,22 @@ +/* eslint-env node */ + +'use strict'; + +module.exports = function(config) { + config.set({ + scripts: [ + { + id: 'jquery', + src: 'jquery-noop.js' + }, { + id: 'angular', + src: '/build/angular.js' + }, { + id: 'angular-animate', + src: '/build/angular-animate.js' + }, { + src: 'app.js' + } + ] + }); +}; diff --git a/benchmarks/animation-bp/jquery-noop.js b/benchmarks/animation-bp/jquery-noop.js new file mode 100644 index 000000000000..8cac7fe4a149 --- /dev/null +++ b/benchmarks/animation-bp/jquery-noop.js @@ -0,0 +1 @@ +// Override me with ?jquery=/bower_components/jquery/dist/jquery.js diff --git a/benchmarks/animation-bp/main.html b/benchmarks/animation-bp/main.html new file mode 100644 index 000000000000..adf0442cae62 --- /dev/null +++ b/benchmarks/animation-bp/main.html @@ -0,0 +1,28 @@ + +
+
+

Large collection of elements animated in and out with ngAnimate

+ +
+
+ Just a plain ol' element +
+
+
+
diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index bf99c58d6a05..daf947967404 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -36,9 +36,9 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate } } - function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + function isAllowed(ruleType, currentAnimation, previousAnimation) { return rules[ruleType].some(function(fn) { - return fn(element, currentAnimation, previousAnimation); + return fn(currentAnimation, previousAnimation); }); } @@ -48,40 +48,40 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate return and ? a && b : a || b; } - rules.join.push(function(element, newAnimation, currentAnimation) { + rules.join.push(function(newAnimation, currentAnimation) { // if the new animation is class-based then we can just tack that on return !newAnimation.structural && hasAnimationClasses(newAnimation); }); - rules.skip.push(function(element, newAnimation, currentAnimation) { + rules.skip.push(function(newAnimation, currentAnimation) { // there is no need to animate anything if no classes are being added and // there is no structural animation that will be triggered return !newAnimation.structural && !hasAnimationClasses(newAnimation); }); - rules.skip.push(function(element, newAnimation, currentAnimation) { + rules.skip.push(function(newAnimation, currentAnimation) { // why should we trigger a new structural animation if the element will // be removed from the DOM anyway? return currentAnimation.event === 'leave' && newAnimation.structural; }); - rules.skip.push(function(element, newAnimation, currentAnimation) { + rules.skip.push(function(newAnimation, currentAnimation) { // if there is an ongoing current animation then don't even bother running the class-based animation return currentAnimation.structural && currentAnimation.state === RUNNING_STATE && !newAnimation.structural; }); - rules.cancel.push(function(element, newAnimation, currentAnimation) { + rules.cancel.push(function(newAnimation, currentAnimation) { // there can never be two structural animations running at the same time return currentAnimation.structural && newAnimation.structural; }); - rules.cancel.push(function(element, newAnimation, currentAnimation) { + rules.cancel.push(function(newAnimation, currentAnimation) { // if the previous animation is already running, but the new animation will // be triggered, but the new animation is structural return currentAnimation.state === RUNNING_STATE && newAnimation.structural; }); - rules.cancel.push(function(element, newAnimation, currentAnimation) { + rules.cancel.push(function(newAnimation, currentAnimation) { // cancel the animation if classes added / removed in both animation cancel each other out, // but only if the current animation isn't structural @@ -181,10 +181,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate return this === arg || !!(this.compareDocumentPosition(arg) & 16); }; - function findCallbacks(parent, element, event) { - var targetNode = getDomNode(element); - var targetParentNode = getDomNode(parent); - + function findCallbacks(targetParentNode, targetNode, event) { var matches = []; var entries = callbackRegistry[event]; if (entries) { @@ -209,11 +206,11 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate }); } - function cleanupEventListeners(phase, element) { - if (phase === 'close' && !element[0].parentNode) { + function cleanupEventListeners(phase, node) { + if (phase === 'close' && !node.parentNode) { // If the element is not attached to a parentNode, it has been removed by // the domOperation, and we can safely remove the event callbacks - $animate.off(element); + $animate.off(node); } } @@ -305,18 +302,15 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate return $animate; - function queueAnimation(element, event, initialOptions) { + function queueAnimation(originalElement, event, initialOptions) { // we always make a copy of the options since // there should never be any side effects on // the input data when running `$animateCss`. var options = copy(initialOptions); - var node, parent; - element = stripCommentsFromElement(element); - if (element) { - node = getDomNode(element); - parent = element.parent(); - } + var element = stripCommentsFromElement(originalElement); + var node = getDomNode(element); + var parentNode = node && node.parentNode; options = prepareAnimationOptions(options); @@ -381,7 +375,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate // there is no point in traversing the same collection of parent ancestors if a followup // animation will be run on the same element that already did all that checking work if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state !== PRE_DIGEST_STATE)) { - skipAnimations = !areAnimationsAllowed(element, parent, event); + skipAnimations = !areAnimationsAllowed(node, parentNode, event); } if (skipAnimations) { @@ -393,7 +387,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate } if (isStructural) { - closeChildAnimations(element); + closeChildAnimations(node); } var newAnimation = { @@ -408,7 +402,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate }; if (hasExistingAnimation) { - var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + var skipAnimationFlag = isAllowed('skip', newAnimation, existingAnimation); if (skipAnimationFlag) { if (existingAnimation.state === RUNNING_STATE) { close(); @@ -418,7 +412,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate return existingAnimation.runner; } } - var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + var cancelAnimationFlag = isAllowed('cancel', newAnimation, existingAnimation); if (cancelAnimationFlag) { if (existingAnimation.state === RUNNING_STATE) { // this will end the animation right away and it is safe @@ -440,7 +434,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate // a joined animation means that this animation will take over the existing one // so an example would involve a leave animation taking over an enter. Then when // the postDigest kicks in the enter will be ignored. - var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + var joinAnimationFlag = isAllowed('join', newAnimation, existingAnimation); if (joinAnimationFlag) { if (existingAnimation.state === RUNNING_STATE) { normalizeAnimationDetails(element, newAnimation); @@ -474,7 +468,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate if (!isValidAnimation) { close(); - clearElementAnimationState(element); + clearElementAnimationState(node); return runner; } @@ -482,9 +476,18 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate var counter = (existingAnimation.counter || 0) + 1; newAnimation.counter = counter; - markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation); $rootScope.$$postDigest(function() { + // It is possible that the DOM nodes inside `originalElement` have been replaced. This can + // happen if the animated element is a transcluded clone and also has a `templateUrl` + // directive on it. Therefore, we must recreate `element` in order to interact with the + // actual DOM nodes. + // Note: We still need to use the old `node` for certain things, such as looking up in + // HashMaps where it was used as the key. + + element = stripCommentsFromElement(originalElement); + var animationDetails = activeAnimationsLookup.get(node); var animationCancelled = !animationDetails; animationDetails = animationDetails || {}; @@ -523,7 +526,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate // isn't allowed to animate from here then we need to clear the state of the element // so that any future animations won't read the expired animation data. if (!isValidAnimation) { - clearElementAnimationState(element); + clearElementAnimationState(node); } return; @@ -535,7 +538,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate ? 'setClass' : animationDetails.event; - markElementAnimationState(element, RUNNING_STATE); + markElementAnimationState(node, RUNNING_STATE); var realRunner = $$animation(element, event, animationDetails.options); // this will update the runner's flow-control events based on @@ -547,7 +550,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate close(!status); var animationDetails = activeAnimationsLookup.get(node); if (animationDetails && animationDetails.counter === counter) { - clearElementAnimationState(getDomNode(element)); + clearElementAnimationState(node); } notifyProgress(runner, event, 'close', {}); }); @@ -557,7 +560,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate function notifyProgress(runner, event, phase, data) { runInNextPostDigestOrNow(function() { - var callbacks = findCallbacks(parent, element, event); + var callbacks = findCallbacks(parentNode, node, event); if (callbacks.length) { // do not optimize this call here to RAF because // we don't know how heavy the callback code here will @@ -567,10 +570,10 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate forEach(callbacks, function(callback) { callback(element, phase, data); }); - cleanupEventListeners(phase, element); + cleanupEventListeners(phase, node); }); } else { - cleanupEventListeners(phase, element); + cleanupEventListeners(phase, node); } }); runner.progress(event, phase, data); @@ -585,8 +588,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate } } - function closeChildAnimations(element) { - var node = getDomNode(element); + function closeChildAnimations(node) { var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); forEach(children, function(child) { var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME), 10); @@ -604,16 +606,11 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate }); } - function clearElementAnimationState(element) { - var node = getDomNode(element); + function clearElementAnimationState(node) { node.removeAttribute(NG_ANIMATE_ATTR_NAME); activeAnimationsLookup.remove(node); } - function isMatchingElement(nodeOrElmA, nodeOrElmB) { - return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); - } - /** * This fn returns false if any of the following is true: * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed @@ -621,54 +618,54 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate * c) the element is not a child of the body * d) the element is not a child of the $rootElement */ - function areAnimationsAllowed(element, parentElement, event) { - var bodyElement = jqLite($document[0].body); - var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML'; - var rootElementDetected = isMatchingElement(element, $rootElement); + function areAnimationsAllowed(node, parentNode, event) { + var bodyNode = $document[0].body; + var rootNode = getDomNode($rootElement); + + var bodyNodeDetected = (node === bodyNode) || node.nodeName === 'HTML'; + var rootNodeDetected = (node === rootNode); var parentAnimationDetected = false; + var elementDisabled = disabledElementsLookup.get(node); var animateChildren; - var elementDisabled = disabledElementsLookup.get(getDomNode(element)); - var parentHost = jqLite.data(element[0], NG_ANIMATE_PIN_DATA); + var parentHost = jqLite.data(node, NG_ANIMATE_PIN_DATA); if (parentHost) { - parentElement = parentHost; + parentNode = getDomNode(parentHost); } - parentElement = getDomNode(parentElement); - - while (parentElement) { - if (!rootElementDetected) { + while (parentNode) { + if (!rootNodeDetected) { // angular doesn't want to attempt to animate elements outside of the application // therefore we need to ensure that the rootElement is an ancestor of the current element - rootElementDetected = isMatchingElement(parentElement, $rootElement); + rootNodeDetected = (parentNode === rootNode); } - if (parentElement.nodeType !== ELEMENT_NODE) { + if (parentNode.nodeType !== ELEMENT_NODE) { // no point in inspecting the #document element break; } - var details = activeAnimationsLookup.get(parentElement) || {}; + var details = activeAnimationsLookup.get(parentNode) || {}; // either an enter, leave or move animation will commence // therefore we can't allow any animations to take place // but if a parent animation is class-based then that's ok if (!parentAnimationDetected) { - var parentElementDisabled = disabledElementsLookup.get(parentElement); + var parentNodeDisabled = disabledElementsLookup.get(parentNode); - if (parentElementDisabled === true && elementDisabled !== false) { + if (parentNodeDisabled === true && elementDisabled !== false) { // disable animations if the user hasn't explicitly enabled animations on the // current element elementDisabled = true; // element is disabled via parent element, no need to check anything else break; - } else if (parentElementDisabled === false) { + } else if (parentNodeDisabled === false) { elementDisabled = false; } parentAnimationDetected = details.structural; } if (isUndefined(animateChildren) || animateChildren === true) { - var value = jqLite.data(parentElement, NG_ANIMATE_CHILDREN_DATA); + var value = jqLite.data(parentNode, NG_ANIMATE_CHILDREN_DATA); if (isDefined(value)) { animateChildren = value; } @@ -677,40 +674,39 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate // there is no need to continue traversing at this point if (parentAnimationDetected && animateChildren === false) break; - if (!bodyElementDetected) { + if (!bodyNodeDetected) { // we also need to ensure that the element is or will be a part of the body element // otherwise it is pointless to even issue an animation to be rendered - bodyElementDetected = isMatchingElement(parentElement, bodyElement); + bodyNodeDetected = (parentNode === bodyNode); } - if (bodyElementDetected && rootElementDetected) { + if (bodyNodeDetected && rootNodeDetected) { // If both body and root have been found, any other checks are pointless, // as no animation data should live outside the application break; } - if (!rootElementDetected) { - // If no rootElement is detected, check if the parentElement is pinned to another element - parentHost = jqLite.data(parentElement, NG_ANIMATE_PIN_DATA); + if (!rootNodeDetected) { + // If `rootNode` is not detected, check if `parentNode` is pinned to another element + parentHost = jqLite.data(parentNode, NG_ANIMATE_PIN_DATA); if (parentHost) { // The pin target element becomes the next parent element - parentElement = getDomNode(parentHost); + parentNode = getDomNode(parentHost); continue; } } - parentElement = parentElement.parentNode; + parentNode = parentNode.parentNode; } var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true; - return allowAnimation && rootElementDetected && bodyElementDetected; + return allowAnimation && rootNodeDetected && bodyNodeDetected; } - function markElementAnimationState(element, state, details) { + function markElementAnimationState(node, state, details) { details = details || {}; details.state = state; - var node = getDomNode(element); node.setAttribute(NG_ANIMATE_ATTR_NAME, state); var oldValue = activeAnimationsLookup.get(node); diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index e1f37c4e4462..f259a6c3faf9 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -168,7 +168,7 @@ describe('animations', function() { inject(function($animate, $rootScope) { $animate.enter(element, parent); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); expect(element[0].parentNode).toEqual(parent[0]); hidden = false; @@ -188,7 +188,7 @@ describe('animations', function() { $animate.enter(element, parent); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); element.addClass('only-allow-this-animation'); @@ -208,7 +208,7 @@ describe('animations', function() { $animate.enter(svgElement, parent); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); svgElement.attr('class', 'element only-allow-this-animation-svg'); @@ -290,7 +290,7 @@ describe('animations', function() { $animate.leave(element); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); expect(element[0].parentNode).toBeFalsy(); }); }); @@ -314,9 +314,9 @@ describe('animations', function() { $animate.enter(element, parent); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should disable all animations on the given element', @@ -328,15 +328,15 @@ describe('animations', function() { expect($animate.enabled(element)).toBeFalsy(); $animate.addClass(element, 'red'); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.enabled(element, true); expect($animate.enabled(element)).toBeTruthy(); $animate.addClass(element, 'blue'); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); expect(capturedAnimation).toBeTruthy(); })); @@ -347,14 +347,14 @@ describe('animations', function() { $animate.enabled(parent, false); $animate.enter(element, parent); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.enabled(parent, true); $animate.enter(element, parent); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); expect(capturedAnimation).toBeTruthy(); })); @@ -370,11 +370,11 @@ describe('animations', function() { $animate.addClass(element, 'red'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(child, 'red'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.enabled(element, true); @@ -402,7 +402,7 @@ describe('animations', function() { $rootScope.items = [1,2,3,4,5]; $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should not attempt to perform an animation on a text node element', @@ -414,7 +414,7 @@ describe('animations', function() { $animate.addClass(textNode, 'some-class'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should not attempt to perform an animation on an empty jqLite collection', @@ -426,7 +426,7 @@ describe('animations', function() { $animate.addClass(emptyNode, 'some-class'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); }) ); @@ -439,7 +439,7 @@ describe('animations', function() { $animate.leave(textNode); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); expect(textNode[0].parentNode).not.toBe(parentNode); })); @@ -455,10 +455,32 @@ describe('animations', function() { $animate.leave(commentNode); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); expect(commentNode[0].parentNode).not.toBe(parentNode); })); + it('enter() should animate a transcluded clone with `templateUrl`', function() { + module(function($compileProvider) { + $compileProvider.directive('foo', function() { + return {templateUrl: 'foo.html'}; + }); + }); + + inject(function($animate, $compile, $rootScope, $templateCache) { + parent.append(jqLite('')); + $templateCache.put('foo.html', '
FOO
'); + $compile(parent)($rootScope); + + expect(capturedAnimation).toBeNull(); + + $rootScope.$apply('showFoo = true'); + + expect(parent.text()).toBe('parentFOO'); + expect(capturedAnimation[0].html()).toBe('
FOO
'); + expect(capturedAnimation[1]).toBe('enter'); + }); + }); + it('enter() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) { expect(parent.children().length).toBe(0); @@ -667,13 +689,13 @@ describe('animations', function() { $animate.removeClass(element, 'something-to-remove'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); element.addClass('something-to-add'); $animate.addClass(element, 'something-to-add'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); }); @@ -689,7 +711,7 @@ describe('animations', function() { parent.append(element); $animate.animate(element, null, toStyle); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); }); }); @@ -700,7 +722,7 @@ describe('animations', function() { parent.append(element); $animate.animate(element, fromStyle); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should perform an animation if only from styles are provided as well as any valid classes', @@ -712,7 +734,7 @@ describe('animations', function() { var options = { removeClass: 'goop' }; $animate.animate(element, fromStyle, null, null, options); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); fromStyle = { color: 'blue' }; options = { addClass: 'goop' }; @@ -816,11 +838,11 @@ describe('animations', function() { var elm1 = $compile('
')($rootScope); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(elm1, 'klass2'); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should skip animations if the element is attached to the $rootElement, but not apart of the body', @@ -834,22 +856,22 @@ describe('animations', function() { newParent.append($rootElement); $rootElement.append(elm1); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(elm1, 'klass2'); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should skip the animation if the element is removed from the DOM before the post digest kicks in', inject(function($animate, $rootScope) { $animate.enter(element, parent); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); element.remove(); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should be blocked when there is an ongoing structural parent animation occurring', @@ -857,7 +879,7 @@ describe('animations', function() { parent.append(element); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.move(parent, parent2); $rootScope.$digest(); @@ -867,7 +889,7 @@ describe('animations', function() { $animate.addClass(element, 'blue'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('should disable all child animations for atleast one turn when a structural animation is issued', @@ -917,7 +939,7 @@ describe('animations', function() { parent.append(element); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(parent, 'rogers'); $rootScope.$digest(); @@ -940,7 +962,7 @@ describe('animations', function() { $animate.addClass(element, 'rumlow'); $animate.move(parent, null, parent2); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); expect(capturedAnimationHistory.length).toBe(0); $rootScope.$digest(); @@ -1193,12 +1215,12 @@ describe('animations', function() { inject(function($animate, $rootScope) { $animate.enter(element, parent); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(element, 'red'); expect(element).not.toHaveClass('red'); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $rootScope.$digest(); expect(capturedAnimation[1]).toBe('enter'); @@ -1227,7 +1249,7 @@ describe('animations', function() { $animate.removeClass(element, 'red'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.addClass(element, 'blue'); $rootScope.$digest(); @@ -1344,7 +1366,7 @@ describe('animations', function() { $animate.removeClass(element, 'four'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); })); it('but not skip the animation if it is a structural animation and if there are no classes to be animated', @@ -1632,7 +1654,7 @@ describe('animations', function() { $animate.addClass(animateElement, 'red'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); // Pin the element to the app root to enable animations $animate.pin(pinElement, $rootElement); @@ -1676,13 +1698,13 @@ describe('animations', function() { $animate.addClass(animateElement, 'red'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.pin(pinElement, pinTargetElement); $animate.addClass(animateElement, 'blue'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); dealoc(pinElement); }); @@ -1720,7 +1742,7 @@ describe('animations', function() { $animate.addClass(animateElement, 'blue'); $rootScope.$digest(); - expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimation).toBeNull(); $animate.enabled(pinHostElement, true); @@ -2437,7 +2459,6 @@ describe('animations', function() { return function($rootElement, $q, $animate, $$AnimateRunner, $document) { defaultFakeAnimationRunner = new $$AnimateRunner(); - $animate.enabled(true); element = jqLite('
element
'); parent = jqLite('
parent
'); @@ -2445,7 +2466,6 @@ describe('animations', function() { $rootElement.append(parent); $rootElement.append(parent2); - jqLite($document[0].body).append($rootElement); }; }));