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

Commit c67bd69

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 71c11e9 commit c67bd69

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
@@ -1298,7 +1298,7 @@ angular.module('ngAnimate', ['ng'])
12981298
parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);
12991299
parentID = parentCounter;
13001300
}
1301-
return parentID + '-' + extractElementNode(element).className;
1301+
return parentID + '-' + extractElementNode(element).getAttribute('class');
13021302
}
13031303

13041304
function animateSetup(animationEvent, element, className) {
@@ -1364,7 +1364,7 @@ angular.module('ngAnimate', ['ng'])
13641364
function animateRun(animationEvent, element, className, activeAnimationComplete) {
13651365
var node = extractElementNode(element);
13661366
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
1367-
if(node.className.indexOf(className) == -1 || !elementData) {
1367+
if(node.getAttribute('class').indexOf(className) == -1 || !elementData) {
13681368
activeAnimationComplete();
13691369
return;
13701370
}

test/ngAnimate/animateSpec.js

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

37313731
expect(element.children().length).toBe(0);
37323732
}));
3733+
3734+
describe('SVG', function() {
3735+
it('should properly apply transitions on an SVG element',
3736+
inject(function($animate, $rootScope, $compile, $rootElement, $sniffer) {
3737+
3738+
//jQuery doesn't handle SVG elements natively. Instead, an add-on library
3739+
//is required which is called jquery.svg.js. Therefore, when jQuery is
3740+
//active here there is no point to test this since it won't work by default.
3741+
if(!$sniffer.transitions || !_jqLiteMode) return;
3742+
3743+
ss.addRule('circle.ng-enter', '-webkit-transition:1s linear all;' +
3744+
'transition:1s linear all;');
3745+
3746+
var element = $compile('<svg width="500" height="500">' +
3747+
'<circle cx="15" cy="5" r="100" fill="orange" ng-if="on" />' +
3748+
'</svg>')($rootScope);
3749+
3750+
$rootElement.append(element);
3751+
jqLite($document[0].body).append($rootElement);
3752+
3753+
$rootScope.$digest();
3754+
3755+
$rootScope.on = true;
3756+
$rootScope.$digest();
3757+
$animate.triggerReflow();
3758+
3759+
var child = element.find('circle');
3760+
3761+
expect(child.hasClass('ng-enter')).toBe(true);
3762+
expect(child.hasClass('ng-enter-active')).toBe(true);
3763+
3764+
browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
3765+
3766+
expect(child.hasClass('ng-enter')).toBe(false);
3767+
expect(child.hasClass('ng-enter-active')).toBe(false);
3768+
}));
3769+
});
37333770
});
37343771
});

0 commit comments

Comments
 (0)