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

Commit

Permalink
fix(ngAnamite): eval ng-animate expression on each animation
Browse files Browse the repository at this point in the history
  • Loading branch information
mhevery committed May 2, 2013
1 parent 80341cb commit fd21c75
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 56 deletions.
102 changes: 49 additions & 53 deletions src/ng/animator.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ var $AnimatorProvider = function() {
* @return {object} the animator object which contains the enter, leave, move, show, hide and animate methods.
*/
var AnimatorService = function(scope, attrs) {
var ngAnimateAttr = attrs.ngAnimate;
var ngAnimateValue = ngAnimateAttr && scope.$eval(ngAnimateAttr);
var animator = {};

/**
Expand Down Expand Up @@ -223,24 +221,22 @@ var $AnimatorProvider = function() {
return animator;

function animateActionFactory(type, beforeFn, afterFn) {
var className = ngAnimateAttr
? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type
: '';
var animationPolyfill = $animation(className);

var polyfillSetup = animationPolyfill && animationPolyfill.setup;
var polyfillStart = animationPolyfill && animationPolyfill.start;

if (!className) {
return function(element, parent, after) {
return function(element, parent, after) {
var ngAnimateValue = scope.$eval(attrs.ngAnimate);
var className = ngAnimateValue
? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type
: '';
var animationPolyfill = $animation(className);
var polyfillSetup = animationPolyfill && animationPolyfill.setup;
var polyfillStart = animationPolyfill && animationPolyfill.start;

if (!className) {
beforeFn(element, parent, after);
afterFn(element, parent, after);
}
} else {
var setupClass = className + '-setup';
var startClass = className + '-start';

return function(element, parent, after) {
} else {
var setupClass = className + '-setup';
var startClass = className + '-start';

if (!parent) {
parent = after ? after.parent() : element.parent();
}
Expand All @@ -255,48 +251,48 @@ var $AnimatorProvider = function() {
element.addClass(setupClass);
beforeFn(element, parent, after);
if (element.length == 0) return done();

var memento = (polyfillSetup || noop)(element);

// $window.setTimeout(beginAnimation, 0); this was causing the element not to animate
// keep at 1 for animation dom rerender
$window.setTimeout(beginAnimation, 1);

function beginAnimation() {
element.addClass(startClass);
if (polyfillStart) {
polyfillStart(element, done, memento);
} else if (isFunction($window.getComputedStyle)) {
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
var w3cTransitionProp = 'transition'; //one day all browsers will have this

var durationKey = 'Duration';
var duration = 0;
};

//we want all the styles defined before and after
forEach(element, function(element) {
if (element.nodeType == 1) {
var globalStyles = $window.getComputedStyle(element) || {};
duration = Math.max(
parseFloat(globalStyles[w3cTransitionProp + durationKey]) ||
parseFloat(globalStyles[vendorTransitionProp + durationKey]) ||
0,
duration);
}
});
$window.setTimeout(done, duration * 1000);
} else {
done();
}
}

function done() {
afterFn(element, parent, after);
element.removeClass(setupClass);
element.removeClass(startClass);
element.removeData(NG_ANIMATE_CONTROLLER);
function beginAnimation() {
element.addClass(startClass);
if (polyfillStart) {
polyfillStart(element, done, memento);
} else if (isFunction($window.getComputedStyle)) {
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
var w3cTransitionProp = 'transition'; //one day all browsers will have this

var durationKey = 'Duration';
var duration = 0;

//we want all the styles defined before and after
forEach(element, function(element) {
if (element.nodeType == 1) {
var globalStyles = $window.getComputedStyle(element) || {};
duration = Math.max(
parseFloat(globalStyles[w3cTransitionProp + durationKey]) ||
parseFloat(globalStyles[vendorTransitionProp + durationKey]) ||
0,
duration);
}
});
$window.setTimeout(done, duration * 1000);
} else {
done();
}
}

function done() {
afterFn(element, parent, after);
element.removeClass(setupClass);
element.removeClass(startClass);
element.removeData(NG_ANIMATE_CONTROLLER);
}
}
}

Expand Down
25 changes: 22 additions & 3 deletions test/ng/animatorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,29 @@ describe("$animator", function() {
}));
});

it("should throw an error when an invalid ng-animate syntax is provided", inject(function($compile, $rootScope) {
describe('anmation evaluation', function () {
it('should re-evaluate the animation expression on each animation', inject(function($animator, $rootScope) {
var parent = jqLite('<div><span></span></div>');
var element = parent.find('span');

$rootScope.animationFn = function () { throw new Error('too early'); };
var animate = $animator($rootScope, { ngAnimate: 'animationFn()' });
var log = '';

$rootScope.animationFn = function () { log = 'abc' };
animate.enter(element, parent);
expect(log).toEqual('abc');

$rootScope.animationFn = function () { log = 'xyz' };
animate.enter(element, parent);
expect(log).toEqual('xyz');
}));
});

it("should throw an error when an invalid ng-animate syntax is provided", inject(function($animator, $rootScope) {
expect(function() {
element = $compile('<div ng-repeat="i in is" ng-animate=":"></div>')($rootScope);
$rootScope.$digest();
var animate = $animator($rootScope, { ngAnimate: ':' });
animate.enter();
}).toThrow("Syntax Error: Token ':' not a primary expression at column 1 of the expression [:] starting at [:].");
}));
});

0 comments on commit fd21c75

Please sign in to comment.