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

SVGAnimatedString handling in animatedRun() #6030

Closed
shirro opened this issue Jan 28, 2014 · 8 comments
Closed

SVGAnimatedString handling in animatedRun() #6030

shirro opened this issue Jan 28, 2014 · 8 comments

Comments

@shirro
Copy link

shirro commented Jan 28, 2014

animateRun() in angular-animate.js doesn't handle SVGAnimatedString giving undefined indexOf method messages when changing classes on SVG nodes.

I wasn't confident to submit a pull request but the following patch seems to work around it for me.

--- ../../vendor/angular.js/build/angular-animate.js    2014-01-28 01:45:13.000000000 +1030
+++ angular-animate.js  2014-01-29 10:21:04.000000000 +1030
@@ -1217,7 +1217,11 @@
       function animateRun(element, className, activeAnimationComplete) {
         var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
         var node = extractElementNode(element);
-        if(node.className.indexOf(className) == -1 || !elementData) {
+        var nodeClassName = node.className;
+        if (angular.isObject(nodeClassName) && nodeClassName.toString() === '[object SVGAnimatedString]') {
+                  nodeClassName = nodeClassName.baseVal;
+        }
+        if(nodeClassName.indexOf(className) == -1 || !elementData) {
           activeAnimationComplete();
           return;
         }
@caitp
Copy link
Contributor

caitp commented Jan 29, 2014

So did you want to submit a pull request for this? :p I don't know how much ngAnimate is being used for SVG (CSS was not the right word to use here!) animation, but it probably doesn't hurt to support it

@shirro
Copy link
Author

shirro commented Jan 29, 2014

@caitp not really. Perhaps someone who is a regular committer could clean it up and do it for me? If I make a habit of hacking on angular I might do it properly next time.

The problem I have is with a heap of ng-class in a ng-repeat in a directive changing classes on certain conditions in an SVG. It works fine until I include the animation module which I wanted for view animations then it starts spitting out indexOf errors in Chrome and Firefox and randomly doesn't make the required class changes.

Edit: And not sure if should be getting baseVal or animVal. I just checked elsewhere in angular and animVal is being used with href elsewhere so perhaps that is the better way.

@matsko
Copy link
Contributor

matsko commented Feb 3, 2014

This code will be changed (animateRun/animateSetup) this week anyways so this issue can be put into consideration.

@shirro
Copy link
Author

shirro commented Feb 3, 2014

Thanks. Meanwhile if anyone sees this and wants to avoid the problem just make sure there are no css transitions on svg elements with directives that support ngAnimate. I had a css hover transition on my svg elements which was triggering animateRun though I had no intention of animating those elements with angular.

It is pretty easy to duplicate:
http://embed.plnkr.co/ZIhUhkwd1hDH6qOWH5Wk/preview

@mprokopowicz
Copy link

Any updates on this one?

@matsko matsko self-assigned this Mar 3, 2014
@matsko
Copy link
Contributor

matsko commented Mar 18, 2014

Yes. I plan on working on getting this in during this week.

matsko added a commit to matsko/angular.js that referenced this issue Apr 3, 2014
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 angular#6030
matsko added a commit to matsko/angular.js that referenced this issue Apr 3, 2014
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 angular#6030
@matsko
Copy link
Contributor

matsko commented Apr 3, 2014

@shirro and @mprokopowicz turns out that all you need is node.getAttribute('class') instead of detecting an SVG element yourself to acquire the className value.

The fix is ready #6973, but I'm not 100% sure if it works since I don't have a visual SVG demo. Please test this out using the files below:

http://ci.angularjs.org/view/Matias'/job/angular.js-matias/704/artifact/build/angular.js
http://ci.angularjs.org/view/Matias'/job/angular.js-matias/704/artifact/build/angular-animate.js
http://ci.angularjs.org/view/Matias'/job/angular.js-matias/704/artifact/build/angular-route.js

Also, as I'm sure that you already know, you need to include jquery.svg.js to make this work for when you're using jQuery on your page. Unfortunately jQuery alone isn't diverse enough to add and remove CSS classes on SVG DOM elements. Fortunately, jqLite works (that is used when jQuery isn't found on the page and Angular uses its own, internal jQuery-style wrapper).

@matsko matsko closed this as completed in c67bd69 Apr 3, 2014
matsko added a commit that referenced this issue Apr 3, 2014
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
@matsko
Copy link
Contributor

matsko commented Apr 3, 2014

Fixed. Landed as c67bd69 and 38ea542 for 1.2.x.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants