Skip to content

Commit 48b1157

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 angular#12874
1 parent 94e5984 commit 48b1157

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
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 sites outside of the body
27+
// we also special case the doc fragement case because our unit test code
28+
// appens 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

+36-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ describe("ngAnimate $$animateCssDriver", function() {
130130
$rootElement.append(to);
131131

132132
// we need to do this so that style detection works
133-
jqLite($document[0].body).append($rootElement);
133+
if ($rootElement[0] !== $document[0]) {
134+
jqLite($document[0].body).append($rootElement);
135+
}
134136
};
135137
}));
136138

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

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

0 commit comments

Comments
 (0)