Chapter 3: Creating move animations with ngRepeat

HTML

<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<script src="https://code.angularjs.org/1.3.2/angular-animate.min.js"></script>
<script src="https://code.angularjs.org/1.3.2/angular-route.min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<div ng-app="myApp">
    <div ng-controller="Ctrl">
        <div style="repeat-container">
            <input ng-model="search.val" />
            <button ng-click="shuffle()">Shuffle</button>
            <div ng-repeat="el in arr track by $index" 
                 class="animate-container">
                <span>{{ el }}</span>
            </div>
        </div>        
    </div>
</div>

CSS

.animate-container {
    position:relative;
    margin-bottom:-1px;
    width: 300px;
    text-align:center;
    border:1px solid black;
    line-height:40px;
}
.repeat-container {
    position:absolute;
}
.animate-container.ng-enter {
    animation: 0.5s item-enter;
    -webkit-animation: 0.5s item-enter;
}
.animate-container.ng-leave {
    animation: 0.5s item-leave;
    -webkit-animation: 0.5s item-leave;
}
.animate-container.ng-move {
    animation: 0.5s item-move;
    -webkit-animation: 0.5s item-move;
}
@keyframes item-enter {
    0% {
        max-height:0;
        left:-300px;
    }
    50% {
        max-height:40px;
        left: -300px;
    }
    100% {
        max-height:40px;
        left: 0px;
    }
}
@keyframes item-leave {
    0% {
        left: 0px;
        max-height:40px;
    }
    50% {
        left: -300px;
        max-height:40px;
    }
    100% {
        left: -300px;
        max-height:0;
    }
}
@keyframes item-move {
    0% {
        opacity:0;
        max-height:0px;
    }
    100% {
        opacity:1;
        max-height:40px;
    }
}
@-webkit-keyframes item-enter {
    0% {
        max-height:0;
        left:-300px;
    }
    50% {
        max-height:40px;
        left: -300px;
    }
    100% {
        max-height:40px;
        left: 0px;
    }
}
@-webkit-keyframes item-leave {
    0% {
        left: 0px;
        max-height:40px;
    }
    50% {
        left: -300px;
        max-height:40px;
    }
    100% {
        left: -300px;
        max-height:0;
    }
}
@-webkit-keyframes item-move {
    0% {
        opacity:0;
        max-height:0px;
    }
    100% {
        opacity:1;
        max-height:40px;
    }
}

JavaScript

angular.module('myApp', ['ngAnimate'])
.controller('Ctrl', function($scope) {
    $scope.arr = [10,15,25,40,45];
    
    // implementation of Knuth in-place shuffle
    function knuthShuffle(a) {
        for(var i = a.length, j, k; i; 
            j = Math.floor(Math.random() * i),
            k = a[--i], 
            a[i] = a[j], 
            a[j] = k);      
        return a;
    }
    
    $scope.shuffle = function() {
        $scope.arr = knuthShuffle($scope.arr);
    };
});