Angular with Masonry Sorting

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/masonry/2.1.08/jquery.masonry.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.5/angular.min.js"></script>
<div class="container">
  <div ng-controller="MainCtrl">
    <div class="row">
      <div class="col-xs-1"></div>
      <div class="col-xs-5">
        <input type="text" class="form-control col-sm-6" placeholder="filter by title" ng-model="nameFilter" />
      </div>
      <!-- Single button -->
      <div class="btn-group col-xs-5">
        <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Sort by .. <span class="caret"></span>

                    </button>
        <ul class="dropdown-menu">
          <li>
            <li> <a href="#" ng-click="changeSort('created')">Sort by last edited</a>

            </li>
            <li> <a href="#" ng-click="changeSort('title')">Sort by title</a>

            </li>
            <li><a href="#" ng-click="changeSort('url')">Sort by url</a>

            </li>
        </ul>
      </div>
    </div>
    <br />
    <hr />
    <ul class="grid" masonry="true">
      <li ng-repeat="item in items | filter: { title: nameFilter } | orderBy:sort:reverse: order"><span>Fiddle Title: </span>
        <br />
        <h5> <a href="http:{{item.url}}" target="_blank"><span>{{item.title}}</span></a></h5>
        <span>Framework: <strong>{{item.framework}}</strong></span>

        <br />
        <br />
        <!--br /> <span>Description: {{item.description}}</span-->
        <!--br /> <span>Created on: {{item.created}}</span> 
                    <small><span>url:</span>

                <br /><a href="http:{{item.url}}" target="_blank"><span>http{{item.url}}</span></a>

                </small>
    ...

CSS

body {
  padding: 20px
}

.grid {
  border: solid 1px #ccc padding: 10px 10px 0 0;
}

.grid li {
  display: inline-block;
  width: 200px;
  height: 100px;
  padding: 5px;
  border: solid 1px #ccc;
  margin: 0 0 10px 10px;
  background: #f6f6f6;
}

.grid li img {
  margin-left: 35%;
  margin-top: 5px
}

/**** Transitions ****/

.masonry,
.masonry li {
  /* apply before masonry add class */
  position: absolute;
  /* important to add it before enter animation start */
  -webkit-transition-duration: .7s;
  transition-duration: .7s;
  -webkit-transition-property: all;
  transition-property: all;
}

.masonry .masonry-enter {
  /* limit animated properties for entering elements */
  -webkit-transition-property: -webkit-transform, opacity;
  transition-property: transform, opacity;
}

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

.masonry-leave,
.masonry-enter.masonry-enter-active {
  opacity: 1;
  -webkit-transform: scale(1);
  transform: scale(1);
}

JavaScript

angular.module('app', [])
  .directive("masonry", function() {
    var NGREPEAT_SOURCE_RE = '<!-- ngRepeat: ((.*) in ((.*?)( track by (.*))?)) -->';
    return {
      compile: function(element, attrs) {
        // auto add animation to brick element
        var animation = attrs.ngAnimate || "'masonry'";
        var $brick = element.children();
        $brick.attr("ng-animate", animation);

        // generate item selector (exclude leaving items)
        var type = $brick.prop('tagName');
        var itemSelector = type + ":not([class$='-leave-active'])";

        return function(scope, element, attrs) {
          var options = angular.extend({
            itemSelector: itemSelector
          }, scope.$eval(attrs.masonry));

          // try to infer model from ngRepeat
          if (!options.model) {
            var ngRepeatMatch = element.html().match(NGREPEAT_SOURCE_RE);
            if (ngRepeatMatch) {
              options.model = ngRepeatMatch[4];
            }
          }

          // initial animation
          element.addClass('masonry');

          // Wait inside directives to render
          setTimeout(function() {
            element.masonry(options);

            element.on("$destroy", function() {
              element.masonry('destroy')
            });

            if (options.model) {
              scope.$apply(function() {
                scope.$watchCollection(options.model, function(_new, _old) {
                  if (_new == _old) return;

                  // Wait inside directives to render
                  setTimeout(function() {
                    element.masonry("reload");
                  });
                });
              });
            }
          });
        };
      }
    };
  })
  .controller('MainCtrl', function($scope, $http) {
    $scope.items = [{
      "framework": "No-Library",
      "version": 0,
      "description": "",
      "title": "CSS-only Tic Tac Toe",
      "url": "//jsfiddle.net/jburns/gsju8Lg7/",
     ...