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

Commit ec13057

Browse files
committed
fix($animate): correctly handle $animate.pin() host elements
This commit fixes two bugs: 1) Previously, animate would assume that a found host element was part of the $rootElement (while it's possible that it is also outside the root). 2) Previously, if a parent of the animated element was pinned to a host element, the host would not be checked regarding animations enabled status etc.
1 parent 52ea411 commit ec13057

File tree

2 files changed

+92
-33
lines changed

2 files changed

+92
-33
lines changed

src/ngAnimate/animateQueue.js

+10-13
Original file line numberDiff line numberDiff line change
@@ -624,25 +624,22 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
624624
// there is no need to continue traversing at this point
625625
if (parentAnimationDetected && animateChildren === false) break;
626626

627-
if (!rootElementDetected) {
628-
// angular doesn't want to attempt to animate elements outside of the application
629-
// therefore we need to ensure that the rootElement is an ancestor of the current element
630-
rootElementDetected = isMatchingElement(parentElement, $rootElement);
631-
if (!rootElementDetected) {
632-
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
633-
if (parentHost) {
634-
parentElement = parentHost;
635-
rootElementDetected = true;
636-
}
637-
}
638-
}
639-
640627
if (!bodyElementDetected) {
641628
// we also need to ensure that the element is or will be apart of the body element
642629
// otherwise it is pointless to even issue an animation to be rendered
643630
bodyElementDetected = isMatchingElement(parentElement, bodyElement);
644631
}
645632

633+
if (!rootElementDetected) {
634+
// If no rootElement is detected, check if the parentElement is pinned to another element
635+
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
636+
if (parentHost) {
637+
// The pin target element becomes the next parent element
638+
parentElement = parentHost;
639+
continue;
640+
}
641+
}
642+
646643
parentElement = parentElement.parent();
647644
}
648645

test/ngAnimate/animateSpec.js

+82-20
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,10 @@ describe("animations", function() {
14831483
return new $$AnimateRunner();
14841484
};
14851485
});
1486+
1487+
return function($animate) {
1488+
$animate.enabled(true);
1489+
}
14861490
}));
14871491

14881492
it('should throw if the arguments are not elements',
@@ -1543,34 +1547,92 @@ describe("animations", function() {
15431547
});
15441548
});
15451549

1546-
it('should adhere to the disabled state of the hosted parent when an element is pinned',
1547-
inject(function($animate, $compile, $document, $rootElement, $rootScope) {
1550+
they('should not animate an element when the pinned element (which is the $prop element), is pinned to an element that is not a child of the $rootElement',
1551+
['same', 'parent', 'grandparent'],
1552+
function(elementRelation) {
1553+
inject(function($animate, $compile, $document, $rootElement, $rootScope) {
15481554

1549-
var innerParent = jqLite('<div></div>');
1550-
jqLite($document[0].body).append(innerParent);
1551-
innerParent.append($rootElement);
1552-
var innerChild = jqLite('<div></div>');
1553-
$rootElement.append(innerChild);
1555+
var pinElement, animateElement, pinTargetElement = jqLite('<div></div>');
15541556

1555-
var element = jqLite('<div></div>');
1556-
jqLite($document[0].body).append(element);
1557+
var innerParent = jqLite('<div></div>');
1558+
jqLite($document[0].body).append(innerParent);
1559+
innerParent.append($rootElement);
1560+
1561+
switch (elementRelation) {
1562+
case 'same':
1563+
pinElement = jqLite('<div id="animate"></div>');
1564+
break;
1565+
case 'parent':
1566+
pinElement = jqLite('<div><div id="animate"></div></div>');
1567+
break;
1568+
case 'grandparent':
1569+
pinElement = jqLite('<div><div><div id="animate"></div></div></div>');
1570+
break;
1571+
}
15571572

1558-
$animate.pin(element, innerChild);
1573+
// Append both the pin element and the pinTargetElement outside the app root
1574+
jqLite($document[0].body).append(pinElement);
1575+
jqLite($document[0].body).append(pinTargetElement);
15591576

1560-
$animate.enabled(innerChild, false);
1577+
animateElement = jqLite($document[0].getElementById('animate'));
15611578

1562-
$animate.addClass(element, 'blue');
1563-
$rootScope.$digest();
1564-
expect(capturedAnimation).toBeFalsy();
1579+
$animate.addClass(animateElement, 'red');
1580+
$rootScope.$digest();
1581+
expect(capturedAnimation).toBeFalsy();
15651582

1566-
$animate.enabled(innerChild, true);
1583+
$animate.pin(pinElement, pinTargetElement);
15671584

1568-
$animate.addClass(element, 'red');
1569-
$rootScope.$digest();
1570-
expect(capturedAnimation).toBeTruthy();
1585+
$animate.addClass(animateElement, 'blue');
1586+
$rootScope.$digest();
1587+
expect(capturedAnimation).toBeFalsy();
15711588

1572-
dealoc(element);
1573-
}));
1589+
dealoc(pinElement);
1590+
});
1591+
});
1592+
1593+
they('should adhere to the disabled state of the hosted parent when the $prop element is pinned',
1594+
['parent'],
1595+
function(elementRelation) {
1596+
inject(function($animate, $compile, $document, $rootElement, $rootScope) {
1597+
1598+
var pinElement, animateElement, pinHostElement = jqLite('<div></div>');
1599+
1600+
var innerParent = jqLite('<div></div>');
1601+
jqLite($document[0].body).append(innerParent);
1602+
innerParent.append($rootElement);
1603+
1604+
switch (elementRelation) {
1605+
case 'same':
1606+
pinElement = jqLite('<div id="animate"></div>');
1607+
break;
1608+
case 'parent':
1609+
pinElement = jqLite('<div><div id="animate"></div></div>');
1610+
break;
1611+
case 'grandparent':
1612+
pinElement = jqLite('<div><div><div id="animate"></div></div></div>');
1613+
break;
1614+
}
1615+
1616+
$rootElement.append(pinHostElement);
1617+
jqLite($document[0].body).append(pinElement);
1618+
animateElement = jqLite($document[0].getElementById('animate'));
1619+
1620+
$animate.pin(pinElement, pinHostElement);
1621+
$animate.enabled(pinHostElement, false);
1622+
1623+
$animate.addClass(animateElement, 'blue');
1624+
$rootScope.$digest();
1625+
expect(capturedAnimation).toBeFalsy();
1626+
1627+
$animate.enabled(pinHostElement, true);
1628+
1629+
$animate.addClass(animateElement, 'red');
1630+
$rootScope.$digest();
1631+
expect(capturedAnimation).toBeTruthy();
1632+
1633+
dealoc(pinElement);
1634+
});
1635+
});
15741636
});
15751637

15761638
describe('callbacks', function() {

0 commit comments

Comments
 (0)