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

Commit bf0f550

Browse files
committed
feat($animate): use promises instead of callbacks for animations
The $animate service (both the service inside of ng and ngAnimate) now makes use of promises instead of callback functions. BREAKING CHANGE Both the API for the cancallation method and the done callback for $animate animations is different. Instead of using a callback function for each of the $animate animation methods, a promise is used instead. ```js //before $animate.enter(element, container, null, callbackFn); //after $animate.enter(element, container).then(callbackFn); ``` The animation can now be cancelled via `$animate.cancel(promise)`. ```js //before var cancelFn = $animate.enter(element, container); cancelFn(); //cancels the animation //after var promise = $animate.enter(element, container); $animate.cancel(promise); //cancels the animation ```
1 parent 2f4437b commit bf0f550

File tree

16 files changed

+312
-268
lines changed

16 files changed

+312
-268
lines changed

src/ng/animate.js

+49-50
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,20 @@ var $AnimateProvider = ['$provide', function($provide) {
8181
return this.$$classNameFilter;
8282
};
8383

84-
this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {
85-
86-
function async(fn) {
87-
fn && $$asyncCallback(fn);
84+
this.$get = ['$$q', '$$asyncCallback', function($$q, $$asyncCallback) {
85+
86+
var currentDefer;
87+
function asyncPromise() {
88+
// only serve one instance of a promise in order to save CPU cycles
89+
if (!currentDefer) {
90+
currentDefer = $$q.defer();
91+
currentDefer.promise.cancel = noop; //ngAnimate.$animate provides this
92+
$$asyncCallback(function() {
93+
currentDefer.resolve();
94+
currentDefer = null;
95+
});
96+
}
97+
return currentDefer.promise;
8898
}
8999

90100
/**
@@ -112,39 +122,34 @@ var $AnimateProvider = ['$provide', function($provide) {
112122
* @name $animate#enter
113123
* @kind function
114124
* @description Inserts the element into the DOM either after the `after` element or
115-
* as the first child within the `parent` element. Once complete, the done() callback
116-
* will be fired (if provided).
125+
* as the first child within the `parent` element. When the function is called a promise
126+
* is returned that will be resolved at a later time.
117127
* @param {DOMElement} element the element which will be inserted into the DOM
118128
* @param {DOMElement} parent the parent element which will append the element as
119129
* a child (if the after element is not present)
120130
* @param {DOMElement} after the sibling element which will append the element
121131
* after itself
122-
* @param {Function=} done callback function that will be called after the element has been
123-
* inserted into the DOM
132+
* @return {Promise} the animation callback promise
124133
*/
125-
enter : function(element, parent, after, done) {
126-
after
127-
? after.after(element)
128-
: parent.prepend(element);
129-
async(done);
130-
return noop;
134+
enter : function(element, parent, after) {
135+
after ? after.after(element)
136+
: parent.prepend(element);
137+
return asyncPromise();
131138
},
132139

133140
/**
134141
*
135142
* @ngdoc method
136143
* @name $animate#leave
137144
* @kind function
138-
* @description Removes the element from the DOM. Once complete, the done() callback will be
139-
* fired (if provided).
145+
* @description Removes the element from the DOM. When the function is called a promise
146+
* is returned that will be resolved at a later time.
140147
* @param {DOMElement} element the element which will be removed from the DOM
141-
* @param {Function=} done callback function that will be called after the element has been
142-
* removed from the DOM
148+
* @return {Promise} the animation callback promise
143149
*/
144-
leave : function(element, done) {
150+
leave : function(element) {
145151
element.remove();
146-
async(done);
147-
return noop;
152+
return asyncPromise();
148153
},
149154

150155
/**
@@ -153,46 +158,43 @@ var $AnimateProvider = ['$provide', function($provide) {
153158
* @name $animate#move
154159
* @kind function
155160
* @description Moves the position of the provided element within the DOM to be placed
156-
* either after the `after` element or inside of the `parent` element. Once complete, the
157-
* done() callback will be fired (if provided).
161+
* either after the `after` element or inside of the `parent` element. When the function
162+
* is called a promise is returned that will be resolved at a later time.
158163
*
159164
* @param {DOMElement} element the element which will be moved around within the
160165
* DOM
161166
* @param {DOMElement} parent the parent element where the element will be
162167
* inserted into (if the after element is not present)
163168
* @param {DOMElement} after the sibling element where the element will be
164169
* positioned next to
165-
* @param {Function=} done the callback function (if provided) that will be fired after the
166-
* element has been moved to its new position
170+
* @return {Promise} the animation callback promise
167171
*/
168-
move : function(element, parent, after, done) {
172+
move : function(element, parent, after) {
169173
// Do not remove element before insert. Removing will cause data associated with the
170174
// element to be dropped. Insert will implicitly do the remove.
171-
return this.enter(element, parent, after, done);
175+
return this.enter(element, parent, after);
172176
},
173177

174178
/**
175179
*
176180
* @ngdoc method
177181
* @name $animate#addClass
178182
* @kind function
179-
* @description Adds the provided className CSS class value to the provided element. Once
180-
* complete, the done() callback will be fired (if provided).
183+
* @description Adds the provided className CSS class value to the provided element.
184+
* When the function is called a promise is returned that will be resolved at a later time.
181185
* @param {DOMElement} element the element which will have the className value
182186
* added to it
183187
* @param {string} className the CSS class which will be added to the element
184-
* @param {Function=} done the callback function (if provided) that will be fired after the
185-
* className value has been added to the element
188+
* @return {Promise} the animation callback promise
186189
*/
187-
addClass : function(element, className, done) {
190+
addClass : function(element, className) {
188191
className = !isString(className)
189192
? (isArray(className) ? className.join(' ') : '')
190193
: className;
191194
forEach(element, function (element) {
192195
jqLiteAddClass(element, className);
193196
});
194-
async(done);
195-
return noop;
197+
return asyncPromise();
196198
},
197199

198200
/**
@@ -201,22 +203,20 @@ var $AnimateProvider = ['$provide', function($provide) {
201203
* @name $animate#removeClass
202204
* @kind function
203205
* @description Removes the provided className CSS class value from the provided element.
204-
* Once complete, the done() callback will be fired (if provided).
206+
* When the function is called a promise is returned that will be resolved at a later time.
205207
* @param {DOMElement} element the element which will have the className value
206208
* removed from it
207209
* @param {string} className the CSS class which will be removed from the element
208-
* @param {Function=} done the callback function (if provided) that will be fired after the
209-
* className value has been removed from the element
210+
* @return {Promise} the animation callback promise
210211
*/
211-
removeClass : function(element, className, done) {
212-
className = isString(className) ?
213-
className :
214-
isArray(className) ? className.join(' ') : '';
212+
removeClass : function(element, className) {
213+
className = !isString(className)
214+
? (isArray(className) ? className.join(' ') : '')
215+
: className;
215216
forEach(element, function (element) {
216217
jqLiteRemoveClass(element, className);
217218
});
218-
async(done);
219-
return noop;
219+
return asyncPromise();
220220
},
221221

222222
/**
@@ -225,22 +225,21 @@ var $AnimateProvider = ['$provide', function($provide) {
225225
* @name $animate#setClass
226226
* @kind function
227227
* @description Adds and/or removes the given CSS classes to and from the element.
228-
* Once complete, the done() callback will be fired (if provided).
228+
* When the function is called a promise is returned that will be resolved at a later time.
229229
* @param {DOMElement} element the element which will have its CSS classes changed
230230
* removed from it
231231
* @param {string} add the CSS classes which will be added to the element
232232
* @param {string} remove the CSS class which will be removed from the element
233-
* @param {Function=} done the callback function (if provided) that will be fired after the
234-
* CSS classes have been set on the element
233+
* @return {Promise} the animation callback promise
235234
*/
236-
setClass : function(element, add, remove, done) {
235+
setClass : function(element, add, remove) {
237236
this.addClass(element, add);
238237
this.removeClass(element, remove);
239-
async(done);
240-
return noop;
238+
return asyncPromise();
241239
},
242240

243-
enabled : noop
241+
enabled : noop,
242+
cancel : noop
244243
};
245244
}];
246245
}];

src/ng/directive/ngIf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ var ngIfDirective = ['$animate', function($animate) {
113113
}
114114
if(block) {
115115
previousElements = getBlockNodes(block.clone);
116-
$animate.leave(previousElements, function() {
116+
$animate.leave(previousElements).then(function() {
117117
previousElements = null;
118118
});
119119
block = null;

src/ng/directive/ngInclude.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate'
198198
currentScope = null;
199199
}
200200
if(currentElement) {
201-
$animate.leave(currentElement, function() {
201+
$animate.leave(currentElement).then(function() {
202202
previousElement = null;
203203
});
204204
previousElement = currentElement;
@@ -228,7 +228,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate'
228228
// directives to non existing elements.
229229
var clone = $transclude(newScope, function(clone) {
230230
cleanupLastIncludeContent();
231-
$animate.enter(clone, null, $element, afterAnimation);
231+
$animate.enter(clone, null, $element).then(afterAnimation);
232232
});
233233

234234
currentScope = newScope;

src/ng/directive/ngSwitch.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ var ngSwitchDirective = ['$animate', function($animate) {
155155
var selected = getBlockNodes(selectedElements[i].clone);
156156
selectedScopes[i].$destroy();
157157
previousElements[i] = selected;
158-
$animate.leave(selected, function() {
158+
$animate.leave(selected).then(function() {
159159
previousElements.splice(i, 1);
160160
});
161161
}

0 commit comments

Comments
 (0)