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

Commit fd21c75

Browse files
committed
fix(ngAnamite): eval ng-animate expression on each animation
1 parent 80341cb commit fd21c75

File tree

2 files changed

+71
-56
lines changed

2 files changed

+71
-56
lines changed

src/ng/animator.js

+49-53
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ var $AnimatorProvider = function() {
147147
* @return {object} the animator object which contains the enter, leave, move, show, hide and animate methods.
148148
*/
149149
var AnimatorService = function(scope, attrs) {
150-
var ngAnimateAttr = attrs.ngAnimate;
151-
var ngAnimateValue = ngAnimateAttr && scope.$eval(ngAnimateAttr);
152150
var animator = {};
153151

154152
/**
@@ -223,24 +221,22 @@ var $AnimatorProvider = function() {
223221
return animator;
224222

225223
function animateActionFactory(type, beforeFn, afterFn) {
226-
var className = ngAnimateAttr
227-
? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type
228-
: '';
229-
var animationPolyfill = $animation(className);
230-
231-
var polyfillSetup = animationPolyfill && animationPolyfill.setup;
232-
var polyfillStart = animationPolyfill && animationPolyfill.start;
233-
234-
if (!className) {
235-
return function(element, parent, after) {
224+
return function(element, parent, after) {
225+
var ngAnimateValue = scope.$eval(attrs.ngAnimate);
226+
var className = ngAnimateValue
227+
? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type
228+
: '';
229+
var animationPolyfill = $animation(className);
230+
var polyfillSetup = animationPolyfill && animationPolyfill.setup;
231+
var polyfillStart = animationPolyfill && animationPolyfill.start;
232+
233+
if (!className) {
236234
beforeFn(element, parent, after);
237235
afterFn(element, parent, after);
238-
}
239-
} else {
240-
var setupClass = className + '-setup';
241-
var startClass = className + '-start';
242-
243-
return function(element, parent, after) {
236+
} else {
237+
var setupClass = className + '-setup';
238+
var startClass = className + '-start';
239+
244240
if (!parent) {
245241
parent = after ? after.parent() : element.parent();
246242
}
@@ -255,48 +251,48 @@ var $AnimatorProvider = function() {
255251
element.addClass(setupClass);
256252
beforeFn(element, parent, after);
257253
if (element.length == 0) return done();
258-
254+
259255
var memento = (polyfillSetup || noop)(element);
260-
256+
261257
// $window.setTimeout(beginAnimation, 0); this was causing the element not to animate
262258
// keep at 1 for animation dom rerender
263259
$window.setTimeout(beginAnimation, 1);
264-
265-
function beginAnimation() {
266-
element.addClass(startClass);
267-
if (polyfillStart) {
268-
polyfillStart(element, done, memento);
269-
} else if (isFunction($window.getComputedStyle)) {
270-
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
271-
var w3cTransitionProp = 'transition'; //one day all browsers will have this
272-
273-
var durationKey = 'Duration';
274-
var duration = 0;
260+
};
275261

276-
//we want all the styles defined before and after
277-
forEach(element, function(element) {
278-
if (element.nodeType == 1) {
279-
var globalStyles = $window.getComputedStyle(element) || {};
280-
duration = Math.max(
281-
parseFloat(globalStyles[w3cTransitionProp + durationKey]) ||
282-
parseFloat(globalStyles[vendorTransitionProp + durationKey]) ||
283-
0,
284-
duration);
285-
}
286-
});
287-
$window.setTimeout(done, duration * 1000);
288-
} else {
289-
done();
290-
}
291-
}
292-
293-
function done() {
294-
afterFn(element, parent, after);
295-
element.removeClass(setupClass);
296-
element.removeClass(startClass);
297-
element.removeData(NG_ANIMATE_CONTROLLER);
262+
function beginAnimation() {
263+
element.addClass(startClass);
264+
if (polyfillStart) {
265+
polyfillStart(element, done, memento);
266+
} else if (isFunction($window.getComputedStyle)) {
267+
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
268+
var w3cTransitionProp = 'transition'; //one day all browsers will have this
269+
270+
var durationKey = 'Duration';
271+
var duration = 0;
272+
273+
//we want all the styles defined before and after
274+
forEach(element, function(element) {
275+
if (element.nodeType == 1) {
276+
var globalStyles = $window.getComputedStyle(element) || {};
277+
duration = Math.max(
278+
parseFloat(globalStyles[w3cTransitionProp + durationKey]) ||
279+
parseFloat(globalStyles[vendorTransitionProp + durationKey]) ||
280+
0,
281+
duration);
282+
}
283+
});
284+
$window.setTimeout(done, duration * 1000);
285+
} else {
286+
done();
298287
}
299288
}
289+
290+
function done() {
291+
afterFn(element, parent, after);
292+
element.removeClass(setupClass);
293+
element.removeClass(startClass);
294+
element.removeData(NG_ANIMATE_CONTROLLER);
295+
}
300296
}
301297
}
302298

test/ng/animatorSpec.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,29 @@ describe("$animator", function() {
336336
}));
337337
});
338338

339-
it("should throw an error when an invalid ng-animate syntax is provided", inject(function($compile, $rootScope) {
339+
describe('anmation evaluation', function () {
340+
it('should re-evaluate the animation expression on each animation', inject(function($animator, $rootScope) {
341+
var parent = jqLite('<div><span></span></div>');
342+
var element = parent.find('span');
343+
344+
$rootScope.animationFn = function () { throw new Error('too early'); };
345+
var animate = $animator($rootScope, { ngAnimate: 'animationFn()' });
346+
var log = '';
347+
348+
$rootScope.animationFn = function () { log = 'abc' };
349+
animate.enter(element, parent);
350+
expect(log).toEqual('abc');
351+
352+
$rootScope.animationFn = function () { log = 'xyz' };
353+
animate.enter(element, parent);
354+
expect(log).toEqual('xyz');
355+
}));
356+
});
357+
358+
it("should throw an error when an invalid ng-animate syntax is provided", inject(function($animator, $rootScope) {
340359
expect(function() {
341-
element = $compile('<div ng-repeat="i in is" ng-animate=":"></div>')($rootScope);
342-
$rootScope.$digest();
360+
var animate = $animator($rootScope, { ngAnimate: ':' });
361+
animate.enter();
343362
}).toThrow("Syntax Error: Token ':' not a primary expression at column 1 of the expression [:] starting at [:].");
344363
}));
345364
});

0 commit comments

Comments
 (0)