AngularJS + Masonry

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/masonry/2.1.08/jquery.masonry.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.5/angular.min.js"></script>

<div ng-controller="MainCtrl">
    <input type="text" ng-model="nameFilter" />
    <a href="#" ng-click="order = 'id'">Order by id</a>
    <a href="#" ng-click="order = 'name'">Order by name</a>
    <a href="#" ng-click="order = 'age'">Order by age</a>
    <a href="#" ng-click="destroy = true">DESTROY</a>

    <ul class="grid" masonry="true" ng-if="!destroy" item-selector="li:not(.zoom-leave)">
        <li ng-repeat="item in items | filter: { name: nameFilter } | orderBy: order" 
            ng-animate="'zoom'">
            <span>{{item.name}}</span>
            <br /> <span>Age: {{item.age}}</span>
            <br /> <span>Company: {{item.company}}</span>
        </li>
    </ul>
</div>

CSS

.grid {
    border: solid 1px #ccc padding: 10px 10px 0 0;
}
.grid li {
    display: inline-block;
    width: 100px;
    height: 100px;
    border: solid 1px #ccc;
    margin: 0 0 10px 10px;
    background: #eee;
}
/**** Transitions ****/
 .masonry, .masonry .masonry-brick {
    -webkit-transition-duration: 0.7s;
    transition-duration: 0.7s;
}
.masonry {
    -webkit-transition-property: height, width;
    -moz-transition-property: height, width;
    -ms-transition-property: height, width;
    -o-transition-property: height, width;
    transition-property: height, width;
}
.masonry .masonry-brick {
    -webkit-transition-property: all;
    transition-property: all;
}

.grid li {
    -wekit-transition: all .75s;
    transition: all .75s;
}

.zoom-enter {
    opacity: 0;
    -webkit-transform: scale(0.1, 0.1);
    transform: scale(0.1, 0.1);
}
.zoom-enter.zoom-enter-active {
    opacity: 1;
    -webkit-transform: scale(1, 1);
    transform: scale(1, 1);
}

.zoom-leave {
    opacity: 1;
    -webkit-transform: scale(1, 1);
    transform: scale(1, 1);
}
.zoom-leave.zoom-leave-active {
    opacity: 0;
    -webkit-transform: scale(0.1, 0.1);
    transform: scale(0.1, 0.1);
}

JavaScript

angular.module('app', [])
.directive("masonry", function ($timeout) {
    // todo: use compile to find attrs ngRepeat and ngAnimate in child
    return function (scope, element, attrs) {
        var options = {};
        var init = false;
        var reloadOn = null;

        var oldDisplay = element.css("display");
        element.css({
            "display": "none"
        });
        
        // TODO: build item selector from ng-animate directive (li:not(.{{ngAnimate}}-leave))
        if (attrs['itemSelector']) options.itemSelector = attrs['itemSelector'];
        if (attrs['columnWidth']) options.columnWidth = attrs["columnWidth"];
        if (attrs["isAnimated"]) options.isAnimated = true;
        
        // reload when given model is updated
        if (attrs["reloadOn"]) {
            reloadOn = attrs["reloadOn"];
        }
        if (!attrs["reloadOn"]) { // try to find in ng-repeat
            var elmHtml = element.html();
            var ngRepeatMatch = elmHtml.match('<!-- ngRepeat: ((.*) in (.*)) -->');
            if (ngRepeatMatch) {
                reloadOn = ngRepeatMatch[3];
            }
        }
        if (reloadOn) {
            scope.$watch(reloadOn, function (_new, _old) {
                if (init === true) {
                    $timeout(function () {
                        element.masonry("reload");
                    }, 100);
                }
            }, true);
        }

        // init masonry
        element.ready(function () {
            element.css("display", oldDisplay);
            element.masonry(options);
            init = true;
        });

        element.on("$destroy", function () {
            element.masonry('destroy')
        });
    };
})
.controller('MainCtrl', function ($scope, $http) {
    $scope.elements = [{
        id: 1,
        name: 'Jhon'
    }];

    $scope.items = $http.get('http://www.json-generator.com/j/dIxZ?indent=4')
        .then(function (response) {
        return response.data.result;
   ...