Angular Animation Directives
by dj_straycat
HTML
<script src="http://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js"></script>
<div ng-controller="MainTest" ng-cloak>
<div ng-repeat="item in testArray" animate-in animate-out>
<input ng-model="item.name" />
<button ng-click="remove(item)">Remove</button>
</div>
<button ng-click="add()">Add</button>
<hr>
<pre ng-bind="testArray|json"</pre>
</div>
CSS
body { padding: 10px; }
JavaScript
angular.module('local', [])
.directive('animateOut', function() {
var defaultAnimation = function(callback) {
this.animate({opacity: 0, height: 0}, 300, callback);
}
return {
restrict: 'A',
inject: { animateOut: 'accessor' },
priority: 50,
link: function($scope, ele, attrs) {
if (!attrs.ngRepeat) return;
var match = attrs.ngRepeat.match(/^\s*(.+)\s+in\s+(.*)\s*$/),
item, collection;
$scope.parentEle = ele.parent();
item = match[1];
collection = match[2];
$scope.collection = function() { return $scope.$eval(collection); }
$scope.$watch($scope.collection, function(val) {
$.isArray(val)&&(val.animatedRemove = function(item, callback) {
var self = this,
i = this.indexOf(item);
var ele = $scope.parentEle.children('.ng-scope:eq('+i+')');
$scope.animateOutFN.call(ele, function() {
self.splice(self.indexOf(item), 1);
$scope.$apply();
callback&&callback();
})
});
})
},
controller: function($scope, animateOut) {
$scope.animateOutFN = animateOut()||defaultAnimation;
}
}
})
.directive('animateIn', function() {
var defaultAnimation = function() {
this.css({ opacity: 0}).animate({opacity: 1}, 300);
}
return {
restrict: 'A',
inject: { animateIn: 'accessor' },
link: function($scope, ele, attrs) {
$scope.animateInFN.apply(ele);
},
controller: function($scope, animateIn) {
$scope.animateInFN = animateIn()||defaultAnimation;
}
}
});
function MainTest($scope) {
$scope.testArray = [];
...