diff --git a/docs/content/error/$animate/nocb.ngdoc b/docs/content/error/$animate/nocb.ngdoc new file mode 100644 index 000000000000..ac5bd360602d --- /dev/null +++ b/docs/content/error/$animate/nocb.ngdoc @@ -0,0 +1,12 @@ +@ngdoc error +@name $animate:nocb +@fullName Do not pass a callback to animate methods +@description + +Since Angular 1.3, the methods of {@link ng.$animate} do not accept a callback as the last parameter. +Instead, they return a promise to which you can attach `then` handlers to be run when the animation completes. + +If you are getting this error then you need to update your code to use the promise-based API. + +See https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9 for information about +the change to the animation API and the changes you need to make. diff --git a/src/ng/animate.js b/src/ng/animate.js index fee391a03730..ba7dc4b56720 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -4,6 +4,13 @@ var $animateMinErr = minErr('$animate'); var ELEMENT_NODE = 1; var NG_ANIMATE_CLASSNAME = 'ng-animate'; + +function assertNoCallback(param) { + if (isFunction(param)) { + throw $animateMinErr('nocb', 'Do not pass a callback to animate methods'); + } +} + function mergeClasses(a,b) { if (!a && !b) return ''; if (!a) return b; @@ -416,6 +423,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ enter: function(element, parent, after, options) { + assertNoCallback(options); parent = parent || after.parent(); domInsert(element, parent, after); return $$animateQueue.push(element, 'enter', options); @@ -440,6 +448,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ move: function(element, parent, after, options) { + assertNoCallback(options); parent = parent || after.parent(); domInsert(element, parent, after); return $$animateQueue.push(element, 'move', options); @@ -459,6 +468,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ leave: function(element, options) { + assertNoCallback(options); return $$animateQueue.push(element, 'leave', options, function() { element.remove(); }); @@ -483,6 +493,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ addClass: function(element, className, options) { + assertNoCallback(options); options = options || {}; options.addClass = mergeClasses(options.addclass, className); return $$animateQueue.push(element, 'addClass', options); @@ -507,6 +518,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ removeClass: function(element, className, options) { + assertNoCallback(options); options = options || {}; options.removeClass = mergeClasses(options.removeClass, className); return $$animateQueue.push(element, 'removeClass', options); @@ -532,6 +544,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ setClass: function(element, add, remove, options) { + assertNoCallback(options); options = options || {}; options.addClass = mergeClasses(options.addClass, add); options.removeClass = mergeClasses(options.removeClass, remove); @@ -560,6 +573,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ animate: function(element, from, to, className, options) { + assertNoCallback(options); options = options || {}; options.from = options.from ? extend(options.from, from) : from; options.to = options.to ? extend(options.to, to) : to; diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 8f9a14b119a1..42bcb7c11485 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -507,6 +507,45 @@ describe("animations", function() { }); }); + it('should throw an error when a callback function is passed as the options param', inject(function($animate, $rootScope, $document) { + + var invalidCallback = function() { }; + var element = $document[0].createElement('div'); + element.setAttribute('id', 'crazy-man'); + + expect(function() { + $animate.enter(element, parent, parent2, invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + expect(function() { + $animate.move(element, parent, parent2, invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + parent.append(element); + + expect(function() { + $animate.addClass(element, 'klass', invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + element.className = 'klass'; + expect(function() { + $animate.removeClass(element, 'klass', invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + expect(function() { + $animate.setClass(element, 'one', 'two', invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + expect(function() { + $animate.leave(element, invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + + var toStyles = { color: 'red' }; + expect(function() { + $animate.animate(element, {}, toStyles, 'klass', invalidCallback); + }).toThrowMinErr('$animate', 'nocb', 'Do not pass a callback to animate methods'); + })); + describe('addClass / removeClass', function() { it('should not perform an animation if there are no valid CSS classes to add', inject(function($animate, $rootScope) {