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/",
...