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

Commit

Permalink
fix($animate): ensure the CSS driver properly works with SVG elements
Browse files Browse the repository at this point in the history
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
  • Loading branch information
matsko committed Apr 3, 2014
1 parent 2db66f5 commit 38ea542
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ angular.module('ngAnimate', ['ng'])
parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);
parentID = parentCounter;
}
return parentID + '-' + extractElementNode(element).className;
return parentID + '-' + extractElementNode(element).getAttribute('class');
}

function animateSetup(animationEvent, element, className, calculationDecorator) {
Expand Down Expand Up @@ -1316,7 +1316,7 @@ angular.module('ngAnimate', ['ng'])
function animateRun(animationEvent, element, className, activeAnimationComplete) {
var node = extractElementNode(element);
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
if(node.className.indexOf(className) == -1 || !elementData) {
if(node.getAttribute('class').indexOf(className) == -1 || !elementData) {
activeAnimationComplete();
return;
}
Expand Down
37 changes: 37 additions & 0 deletions test/ngAnimate/animateSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3652,5 +3652,42 @@ describe("ngAnimate", function() {

expect(element.children().length).toBe(0);
}));

describe('SVG', function() {
it('should properly apply transitions on an SVG element',
inject(function($animate, $rootScope, $compile, $rootElement, $sniffer) {

//jQuery doesn't handle SVG elements natively. Instead, an add-on library
//is required which is called jquery.svg.js. Therefore, when jQuery is
//active here there is no point to test this since it won't work by default.
if(!$sniffer.transitions || !_jqLiteMode) return;

ss.addRule('circle.ng-enter', '-webkit-transition:1s linear all;' +
'transition:1s linear all;');

var element = $compile('<svg width="500" height="500">' +
'<circle cx="15" cy="5" r="100" fill="orange" ng-if="on" />' +
'</svg>')($rootScope);

$rootElement.append(element);
jqLite($document[0].body).append($rootElement);

$rootScope.$digest();

$rootScope.on = true;
$rootScope.$digest();
$animate.triggerReflow();

var child = element.find('circle');

expect(child.hasClass('ng-enter')).toBe(true);
expect(child.hasClass('ng-enter-active')).toBe(true);

browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });

expect(child.hasClass('ng-enter')).toBe(false);
expect(child.hasClass('ng-enter-active')).toBe(false);
}));
});
});
});

0 comments on commit 38ea542

Please sign in to comment.