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

Commit 240d589

Browse files
committed
fix(ngAnimate): ensure anchoring uses body as a container when needed
Prior to this fix anchoring would allow for a container to be a document node or something higher beyond the body tag. This patch makes it fall back to body incase the rootElement node exists as a parent ancestor. Closes #12872
1 parent 64ef084 commit 240d589

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

src/ngAnimate/animateCssDriver.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
99
var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
1010
var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
1111

12+
function isDocumentFragment(node) {
13+
return node.parentNode && node.parentNode.nodeType === 11;
14+
}
15+
1216
this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document',
1317
function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) {
1418

@@ -18,7 +22,12 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
1822
var bodyNode = $document[0].body;
1923
var rootNode = getDomNode($rootElement);
2024

21-
var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode);
25+
var rootBodyElement = jqLite(
26+
// this is to avoid using something that exists outside of the body
27+
// we also special case the doc fragement case because our unit test code
28+
// appends the $rootElement to the body after the app has been bootstrapped
29+
isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
30+
);
2231

2332
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
2433

test/ngAnimate/animateCssDriverSpec.js

+41-2
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,14 @@ describe("ngAnimate $$animateCssDriver", function() {
129129
$rootElement.append(from);
130130
$rootElement.append(to);
131131

132-
// we need to do this so that style detection works
133-
jqLite($document[0].body).append($rootElement);
132+
var doc = $document[0];
133+
134+
// there is one test in here that expects the rootElement
135+
// to superceed the body node
136+
if (!$rootElement[0].contains(doc.body)) {
137+
// we need to do this so that style detection works
138+
jqLite(doc.body).append($rootElement);
139+
}
134140
};
135141
}));
136142

@@ -975,6 +981,39 @@ describe("ngAnimate $$animateCssDriver", function() {
975981

976982
expect(completed).toBe(true);
977983
}));
984+
985+
it("should use <body> as the element container if the rootElement exists outside of the <body> tag", function() {
986+
module(function($provide) {
987+
$provide.factory('$rootElement', function($document) {
988+
return jqLite($document[0].querySelector('html'));
989+
});
990+
});
991+
inject(function($rootElement, $rootScope, $animate, $document) {
992+
ss.addRule('.ending-element', 'width:9999px; height:6666px; display:inline-block;');
993+
994+
var fromAnchor = jqLite('<div></div>');
995+
from.append(fromAnchor);
996+
997+
var toAnchor = jqLite('<div></div>');
998+
to.append(toAnchor);
999+
1000+
$rootElement.append(fromAnchor);
1001+
$rootElement.append(toAnchor);
1002+
1003+
var completed = false;
1004+
driver({
1005+
from: fromAnimation,
1006+
to: toAnimation,
1007+
anchors: [{
1008+
'out': fromAnchor,
1009+
'in': toAnchor
1010+
}]
1011+
}).start();
1012+
1013+
var clone = captureLog[2].element[0];
1014+
expect(clone.parentNode).toBe($document[0].body);
1015+
});
1016+
});
9781017
});
9791018
});
9801019
});

0 commit comments

Comments
 (0)