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

Commit 38ea542

Browse files
committed
fix($animate): ensure the CSS driver properly works with SVG elements
The default CSS driver in ngAnimate directly uses node.className when reading the CSS class string on the given element. While this works fine with standard HTML DOM elements, SVG elements have their own DOM property. By switching to use node.getAttribute, ngAnimate can extract the element's className value without throwing an exception. When using jQuery over jqLite, ngAnimate will not properly handle SVG elements for an animation. This is because jQuery doesn't process SVG elements within it's DOM operation code by default. To get this to work, simply include the jquery.svg.js JavaScript file into your application. Closes #6030
1 parent 2db66f5 commit 38ea542

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/ngAnimate/animate.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@ angular.module('ngAnimate', ['ng'])
12111211
parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);
12121212
parentID = parentCounter;
12131213
}
1214-
return parentID + '-' + extractElementNode(element).className;
1214+
return parentID + '-' + extractElementNode(element).getAttribute('class');
12151215
}
12161216

12171217
function animateSetup(animationEvent, element, className, calculationDecorator) {
@@ -1316,7 +1316,7 @@ angular.module('ngAnimate', ['ng'])
13161316
function animateRun(animationEvent, element, className, activeAnimationComplete) {
13171317
var node = extractElementNode(element);
13181318
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
1319-
if(node.className.indexOf(className) == -1 || !elementData) {
1319+
if(node.getAttribute('class').indexOf(className) == -1 || !elementData) {
13201320
activeAnimationComplete();
13211321
return;
13221322
}

test/ngAnimate/animateSpec.js

+37
Original file line numberDiff line numberDiff line change
@@ -3652,5 +3652,42 @@ describe("ngAnimate", function() {
36523652

36533653
expect(element.children().length).toBe(0);
36543654
}));
3655+
3656+
describe('SVG', function() {
3657+
it('should properly apply transitions on an SVG element',
3658+
inject(function($animate, $rootScope, $compile, $rootElement, $sniffer) {
3659+
3660+
//jQuery doesn't handle SVG elements natively. Instead, an add-on library
3661+
//is required which is called jquery.svg.js. Therefore, when jQuery is
3662+
//active here there is no point to test this since it won't work by default.
3663+
if(!$sniffer.transitions || !_jqLiteMode) return;
3664+
3665+
ss.addRule('circle.ng-enter', '-webkit-transition:1s linear all;' +
3666+
'transition:1s linear all;');
3667+
3668+
var element = $compile('<svg width="500" height="500">' +
3669+
'<circle cx="15" cy="5" r="100" fill="orange" ng-if="on" />' +
3670+
'</svg>')($rootScope);
3671+
3672+
$rootElement.append(element);
3673+
jqLite($document[0].body).append($rootElement);
3674+
3675+
$rootScope.$digest();
3676+
3677+
$rootScope.on = true;
3678+
$rootScope.$digest();
3679+
$animate.triggerReflow();
3680+
3681+
var child = element.find('circle');
3682+
3683+
expect(child.hasClass('ng-enter')).toBe(true);
3684+
expect(child.hasClass('ng-enter-active')).toBe(true);
3685+
3686+
browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
3687+
3688+
expect(child.hasClass('ng-enter')).toBe(false);
3689+
expect(child.hasClass('ng-enter-active')).toBe(false);
3690+
}));
3691+
});
36553692
});
36563693
});

0 commit comments

Comments
 (0)