Skip to content

Commit 197a74d

Browse files
committed
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 angular#11703
1 parent 1268b17 commit 197a74d

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

src/ngAnimate/animateQueue.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,14 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
221221
};
222222

223223
function queueAnimation(element, event, options) {
224+
var node, parent;
224225
element = stripCommentsFromElement(element);
225-
var node = element[0];
226+
if (element) {
227+
node = element[0];
228+
parent = element.parent();
229+
}
226230

227231
options = prepareAnimationOptions(options);
228-
var parent = element.parent();
229232

230233
// we create a fake runner with a working promise.
231234
// These methods will become available after the digest has passed
@@ -235,7 +238,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
235238
// a jqLite wrapper that contains only comment nodes... If this
236239
// happens then there is no way we can perform an animation
237240
if (!node) {
238-
runner.end();
241+
close();
239242
return runner;
240243
}
241244

src/ngAnimate/shared.js

+21-10
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,29 @@ function removeFromArray(arr, val) {
7272
}
7373

7474
function stripCommentsFromElement(element) {
75-
if (element.nodeType === ELEMENT_NODE) {
76-
return jqLite(element);
75+
if (element instanceof jqLite) {
76+
switch (element.length) {
77+
case 0:
78+
return [];
79+
break;
80+
81+
case 1:
82+
// there is no point of stripping anything if the element
83+
// is the only element within the jqLite wrapper.
84+
// (it's important that we retain the element instance.)
85+
if (element[0].nodeType === ELEMENT_NODE) {
86+
return element;
87+
}
88+
break;
89+
90+
default:
91+
return jqLite(extractElementNode(element));
92+
break;
93+
}
7794
}
78-
if (element.length === 0) return [];
7995

80-
// there is no point of stripping anything if the element
81-
// is the only element within the jqLite wrapper.
82-
// (it's important that we retain the element instance.)
83-
if (element.length === 1) {
84-
return element[0].nodeType === ELEMENT_NODE && element;
85-
} else {
86-
return jqLite(extractElementNode(element));
96+
if (element.nodeType === ELEMENT_NODE) {
97+
return jqLite(element);
8798
}
8899
}
89100

test/ngAnimate/animateSpec.js

+47
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,53 @@ describe("animations", function() {
245245
expect(capturedAnimation).toBeFalsy();
246246
}));
247247

248+
it('should not attempt to perform an animation on a text node element',
249+
inject(function($rootScope, $animate) {
250+
251+
element.html('hello there');
252+
var textNode = element[0].firstChild;
253+
254+
$animate.addClass(textNode, 'some-class');
255+
$rootScope.$digest();
256+
257+
expect(capturedAnimation).toBeFalsy();
258+
259+
textNode = jqLite(textNode);
260+
$animate.addClass(textNode, 'another-class');
261+
$rootScope.$digest();
262+
263+
expect(capturedAnimation).toBeFalsy();
264+
}));
265+
266+
it('should perform the leave domOperation if a text node is used',
267+
inject(function($rootScope, $animate) {
268+
269+
element.html('hello there');
270+
var textNode = element[0].firstChild;
271+
var parentNode = textNode.parentNode;
272+
273+
$animate.leave(textNode);
274+
$rootScope.$digest();
275+
expect(capturedAnimation).toBeFalsy();
276+
expect(textNode.parentNode).not.toBe(parentNode);
277+
}));
278+
279+
it('should perform the leave domOperation if a comment node is used',
280+
inject(function($rootScope, $animate, $document) {
281+
282+
var doc = $document[0];
283+
284+
element.html('hello there');
285+
var commentNode = doc.createComment('test comment');
286+
var parentNode = element[0];
287+
parentNode.appendChild(commentNode);
288+
289+
$animate.leave(commentNode);
290+
$rootScope.$digest();
291+
expect(capturedAnimation).toBeFalsy();
292+
expect(commentNode.parentNode).not.toBe(parentNode);
293+
}));
294+
248295
it('enter() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) {
249296
expect(parent.children().length).toBe(0);
250297

0 commit comments

Comments
 (0)