From b80dfc9b2e36dee06c3f0d26eb15e2e80ef28f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 4 May 2015 16:08:30 -0700 Subject: [PATCH] fix(ngAnimate): ensure animations are not attempted on text nodes With the large refactor in 1.4.0-rc.0, the detection code failed to filter out text nodes from animating. This fix ensures that now properly happens. Closes #11703 --- src/ngAnimate/animateQueue.js | 9 +++++--- src/ngAnimate/shared.js | 31 +++++++++++++++++--------- test/ngAnimate/animateSpec.js | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 00dd4e3e62db..fb7ca3c651ba 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -221,11 +221,14 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { }; function queueAnimation(element, event, options) { + var node, parent; element = stripCommentsFromElement(element); - var node = element[0]; + if (element) { + node = element[0]; + parent = element.parent(); + } options = prepareAnimationOptions(options); - var parent = element.parent(); // we create a fake runner with a working promise. // These methods will become available after the digest has passed @@ -235,7 +238,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { // a jqLite wrapper that contains only comment nodes... If this // happens then there is no way we can perform an animation if (!node) { - runner.end(); + close(); return runner; } diff --git a/src/ngAnimate/shared.js b/src/ngAnimate/shared.js index bfa5a80c5916..fc906286253c 100644 --- a/src/ngAnimate/shared.js +++ b/src/ngAnimate/shared.js @@ -72,18 +72,29 @@ function removeFromArray(arr, val) { } function stripCommentsFromElement(element) { - if (element.nodeType === ELEMENT_NODE) { - return jqLite(element); + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return []; + break; + + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; + + default: + return jqLite(extractElementNode(element)); + break; + } } - if (element.length === 0) return []; - // there is no point of stripping anything if the element - // is the only element within the jqLite wrapper. - // (it's important that we retain the element instance.) - if (element.length === 1) { - return element[0].nodeType === ELEMENT_NODE && element; - } else { - return jqLite(extractElementNode(element)); + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); } } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index cf4d4fefd45a..ccb2d2eff09a 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -245,6 +245,47 @@ describe("animations", function() { expect(capturedAnimation).toBeFalsy(); })); + it('should not attempt to perform an animation on a text node element', + inject(function($rootScope, $animate) { + + element.html('hello there'); + var textNode = jqLite(element[0].firstChild); + + $animate.addClass(textNode, 'some-class'); + $rootScope.$digest(); + + expect(capturedAnimation).toBeFalsy(); + })); + + it('should perform the leave domOperation if a text node is used', + inject(function($rootScope, $animate) { + + element.html('hello there'); + var textNode = jqLite(element[0].firstChild); + var parentNode = textNode[0].parentNode; + + $animate.leave(textNode); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + expect(textNode[0].parentNode).not.toBe(parentNode); + })); + + it('should perform the leave domOperation if a comment node is used', + inject(function($rootScope, $animate, $document) { + + var doc = $document[0]; + + element.html('hello there'); + var commentNode = jqLite(doc.createComment('test comment')); + var parentNode = element[0]; + parentNode.appendChild(commentNode[0]); + + $animate.leave(commentNode); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + expect(commentNode[0].parentNode).not.toBe(parentNode); + })); + 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);