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
This commit is contained in:
@@ -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) {
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user