Skip to content

Commit

Permalink
fix(ngAnimate): do not use jQuery class API
Browse files Browse the repository at this point in the history
jQeury's class API causes problems with SVG elements --- using jqLite in all cases
prevents issues.

Closes angular#10024
Closes angular#10329
  • Loading branch information
caitp committed Dec 4, 2014
1 parent cb19229 commit 40a537c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 26 deletions.
40 changes: 19 additions & 21 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,12 @@ angular.module('ngAnimate', ['ng'])
return extractElementNode(elm1) == extractElementNode(elm2);
}

var $coreAnimate;

$provide.decorator('$animate',
['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest',
function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest) {

$coreAnimate = $delegate;
$rootElement.data(NG_ANIMATE_STATE, rootAnimateState);

// Wait until all directive and route-related templates are downloaded and
Expand Down Expand Up @@ -1380,11 +1382,9 @@ angular.module('ngAnimate', ['ng'])

//the ng-animate class does nothing, but it's here to allow for
//parent animations to find and cancel child animations when needed
element.addClass(NG_ANIMATE_CLASS_NAME);
$delegate.$$addClassImmediately(element, NG_ANIMATE_CLASS_NAME);
if (options && options.tempClasses) {
forEach(options.tempClasses, function(className) {
element.addClass(className);
});
$delegate.$$addClassImmediately(element, options.tempClasses);
}

var localAnimationCount = globalAnimationCounter++;
Expand Down Expand Up @@ -1460,9 +1460,7 @@ angular.module('ngAnimate', ['ng'])

closeAnimation.hasBeenRun = true;
if (options && options.tempClasses) {
forEach(options.tempClasses, function(className) {
element.removeClass(className);
});
$delegate.$$removeClassImmediately(element, options.tempClasses);
}

var data = element.data(NG_ANIMATE_STATE);
Expand Down Expand Up @@ -1523,7 +1521,7 @@ angular.module('ngAnimate', ['ng'])
}

if (removeAnimations || !data.totalActive) {
element.removeClass(NG_ANIMATE_CLASS_NAME);
$delegate.$$removeClassImmediately(element, NG_ANIMATE_CLASS_NAME);
element.removeData(NG_ANIMATE_STATE);
}
}
Expand Down Expand Up @@ -1764,22 +1762,22 @@ angular.module('ngAnimate', ['ng'])
var staggerCacheKey = cacheKey + ' ' + staggerClassName;
var applyClasses = !lookupCache[staggerCacheKey];

applyClasses && element.addClass(staggerClassName);
applyClasses && $coreAnimate.$$addClassImmediately(element, staggerClassName);

stagger = getElementAnimationDetails(element, staggerCacheKey);

applyClasses && element.removeClass(staggerClassName);
applyClasses && $coreAnimate.$$removeClassImmediately(element, staggerClassName);
}

element.addClass(className);
$coreAnimate.$$addClassImmediately(element, className);

var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};
var timings = getElementAnimationDetails(element, eventCacheKey);
var transitionDuration = timings.transitionDuration;
var animationDuration = timings.animationDuration;

if (structural && transitionDuration === 0 && animationDuration === 0) {
element.removeClass(className);
$coreAnimate.$$removeClassImmediately(element, className);
return false;
}

Expand Down Expand Up @@ -1851,7 +1849,7 @@ angular.module('ngAnimate', ['ng'])
}

if (!staggerTime) {
element.addClass(activeClassName);
$coreAnimate.$$addClassImmediately(element, activeClassName);
if (elementData.blockTransition) {
blockTransitions(node, false);
}
Expand All @@ -1861,7 +1859,7 @@ angular.module('ngAnimate', ['ng'])
var timings = getElementAnimationDetails(element, eventCacheKey);
var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
if (maxDuration === 0) {
element.removeClass(activeClassName);
$coreAnimate.$$removeClassImmediately(element, activeClassName);
animateClose(element, className);
activeAnimationComplete();
return;
Expand Down Expand Up @@ -1896,7 +1894,7 @@ angular.module('ngAnimate', ['ng'])

var staggerTimeout;
if (staggerTime > 0) {
element.addClass(pendingClassName);
$coreAnimate.$$addClassImmediately(element, pendingClassName);
staggerTimeout = $timeout(function() {
staggerTimeout = null;

Expand All @@ -1907,8 +1905,8 @@ angular.module('ngAnimate', ['ng'])
blockAnimations(node, false);
}

element.addClass(activeClassName);
element.removeClass(pendingClassName);
$coreAnimate.$$addClassImmediately(element, activeClassName);
$coreAnimate.$$removeClassImmediately(element, pendingClassName);

if (styles) {
if (timings.transitionDuration === 0) {
Expand All @@ -1935,8 +1933,8 @@ angular.module('ngAnimate', ['ng'])
// timeout done method.
function onEnd() {
element.off(css3AnimationEvents, onAnimationProgress);
element.removeClass(activeClassName);
element.removeClass(pendingClassName);
$coreAnimate.$$removeClassImmediately(element, activeClassName);
$coreAnimate.$$removeClassImmediately(element, pendingClassName);
if (staggerTimeout) {
$timeout.cancel(staggerTimeout);
}
Expand Down Expand Up @@ -2024,7 +2022,7 @@ angular.module('ngAnimate', ['ng'])
}

function animateClose(element, className) {
element.removeClass(className);
$coreAnimate.$$removeClassImmediately(element, className);
var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
if (data) {
if (data.running) {
Expand Down
10 changes: 5 additions & 5 deletions test/ngAnimate/animateSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5316,7 +5316,7 @@ describe("ngAnimate", function() {
//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;
if (!$sniffer.transitions) return;

ss.addRule('circle.ng-enter', '-webkit-transition:1s linear all;' +
'transition:1s linear all;');
Expand All @@ -5336,13 +5336,13 @@ describe("ngAnimate", function() {

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

expect(child.hasClass('ng-enter')).toBe(true);
expect(child.hasClass('ng-enter-active')).toBe(true);
expect(jqLiteHasClass(child[0], 'ng-enter')).toBe(true);
expect(jqLiteHasClass(child[0], '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);
expect(jqLiteHasClass(child[0], 'ng-enter')).toBe(false);
expect(jqLiteHasClass(child[0], 'ng-enter-active')).toBe(false);
}));


Expand Down

0 comments on commit 40a537c

Please sign in to comment.