diff --git a/css/angular.css b/css/angular.css index 46fee32d9757..029d3a7d24bc 100644 --- a/css/angular.css +++ b/css/angular.css @@ -18,5 +18,5 @@ ng\:form { * animations. The clip (!ie) and zoom (ie) CSS properties are used * since they trigger a transition without making the browser * animate anything and they're both highly underused CSS properties */ -.ng-animate { clip:rect(1px, auto, auto, 0); -ms-zoom:1.0001; } -.ng-animate-active { clip:rect(0, auto, auto, 0); -ms-zoom:1; } +.ng-animate-start { clip:rect(0, auto, auto, 0); -ms-zoom:1.0001; } +.ng-animate-active { clip:rect(-1px, auto, auto, 0); -ms-zoom:1; } diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index ec7b38aacff6..72c29cc374f4 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -815,6 +815,8 @@ angular.module('ngAnimate', ['ng']) var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; + var NG_ANIMATE_FALLBACK_CLASS_NAME = 'ng-animate-start'; + var NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME = 'ng-animate-active'; var lookupCache = {}; var parentCounter = 0; @@ -954,11 +956,13 @@ angular.module('ngAnimate', ['ng']) var node = element[0]; //temporarily disable the transition so that the enter styles //don't animate twice (this is here to avoid a bug in Chrome/FF). + var activeClassName = ''; if(timings.transitionDuration > 0) { + element.addClass(NG_ANIMATE_FALLBACK_CLASS_NAME); + activeClassName += NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME + ' '; node.style[TRANSITION_PROP + PROPERTY_KEY] = 'none'; } - var activeClassName = 'ng-animate-active '; forEach(className.split(' '), function(klass, i) { activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; }); @@ -1118,6 +1122,7 @@ angular.module('ngAnimate', ['ng']) function animateClose(element, className) { element.removeClass(className); + element.removeClass(NG_ANIMATE_FALLBACK_CLASS_NAME); element.removeData(NG_ANIMATE_CSS_DATA_KEY); } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index dee9bcba8604..562d94a047a3 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -814,7 +814,7 @@ describe("ngAnimate", function() { $timeout.flush(); expect(child.attr('style') || '').not.toContain('transition-property'); - expect(child.hasClass('ng-animate')).toBe(true); + expect(child.hasClass('ng-animate-start')).toBe(true); expect(child.hasClass('ng-animate-active')).toBe(true); browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1000 }); @@ -845,6 +845,53 @@ describe("ngAnimate", function() { expect(child2.hasClass('ng-animate-active')).toBe(false); })); + it("should not apply the fallback classes if no animations are going on or if CSS animations are going on", + inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { + + if (!$sniffer.animations) return; + + ss.addRule('.transitions', '-webkit-transition:1s linear all;' + + 'transition:1s linear all'); + + ss.addRule('.keyframes', '-webkit-animation:my_animation 1s;' + + 'animation:my_animation 1s'); + + var element = $compile('
...
')($rootScope); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $animate.enabled(false); + + $animate.addClass(element, 'klass'); + + expect(element.hasClass('ng-animate-start')).toBe(false); + + element.removeClass('klass'); + + $animate.enabled(true); + + $animate.addClass(element, 'klass'); + + $timeout.flush(); + + expect(element.hasClass('ng-animate-start')).toBe(true); + expect(element.hasClass('ng-animate-active')).toBe(true); + + browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + + expect(element.hasClass('ng-animate-start')).toBe(false); + expect(element.hasClass('ng-animate-active')).toBe(false); + + element.attr('class', 'keyframes'); + + $animate.addClass(element, 'klass2'); + + $timeout.flush(); + + expect(element.hasClass('ng-animate-start')).toBe(false); + expect(element.hasClass('ng-animate-active')).toBe(false); + })); + it("should skip transitions if disabled and run when enabled", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) {