<!DOCTYPE html>
<html ng-app='app'>
<head>
<link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="phones.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller='MyCtrl'>
<table class="table">
<thead>
<tr sort-group="myGrid">
<th ng-repeat="column in columns" sort-by="{{column.name}}" >
{{column.label}}
<span
ng-show="myGrid.sort.column === column.name"
class="text-primary glyphicon"
ng-class="{'glyphicon-arrow-up': myGrid.sort.direction==='+', 'glyphicon-arrow-down': myGrid.sort.direction==='-' }">
</span>
</th>
</tr>
<!-- filter by column -->
<tr>
<td class="input" ng-repeat="column in columns" >
<input placeholder="{{column.label}}" ng-model="myFilter[column.name]">
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="phone in phones | filter:myFilter:comparator | orderBy: myGrid.sort.orderByExp()">
<td ng-repeat="column in columns">
{{phone[column.name]}}
</td>
</tr>
</tbody>
</table>
</body>
</html>
angular.module('app', [])
.directive('sortGroup', function() {
return {
restrict: 'A',
controller: function($scope, $element, $attrs) {
// create a namespace to host the different sort bindings
var ns = $scope[$attrs.sortGroup] = {};
var sort = ns.sort = {
column : '',
direction : '+',
orderByExp : function() {
return sort.direction + sort.column;
}
};
// method called by child sort-by directives
this.toggleSort = function(column) {
if (column === sort.column) {
// same column, toggle the direction asc <-> desc
sort.direction = (sort.direction === '+' ? '-' : '+');
} else {
// new column, sort asc
sort.column = column;
sort.direction = '+';
}
$scope.$apply();
}
}
}
})
.directive('sortBy', function() {
return {
restrict: 'A',
require: '^sortGroup',
link: function(scope, el, attrs, ctrl) {
el.on('click', function(e) {
ctrl.toggleSort(attrs.sortBy);
})
}
}
})
.directive('filterGroup', function() {
function FilterGroup(joinOp) {
this.filters = [];
function and() {
var ok = true;
for (var i = 0; i < this.filters.length; i++) {
var f = this.filters[i];
ok = ok && f.applyFilter();
}
return ok;
}
function or() {
var ok = true;
for (var i = 0; i < this.filters.length; i++) {
var f = this.filters[i];
ok = ok||f.applyFilter();
}
return ok;
}
this.filterFn = function() {
return joinOp === 'or' ? or : anf;
}
}
return {
restrict: 'AE',
controller: function($scope, $element, $attrs) {
// create a namespace to host the different sort bindings
var fg = $scope[$attrs.filterGroup] = new FilterGroup($attrs.op);
this. addFilter = function(filter) {
fg.filters.add(filter);
};
}
}
})
.directive('filter', function(){
function Filter(predicate) {
var comps = {
'string': {
'=': function(act, exp) { return act === exp; },
'in': function(act, exp) { return act.indexOf(exp) >= 0 ; },
'st': function(act, exp) { return act.indexOf(exp) === 0; },
'end': function(act, exp) { return act.indexOf(exp) === (act.length - exp.length); }
},
'number': {
'=': function(act, exp) { return act === exp; },
'!=': function(act, exp) { return act !== exp; },
'<=': function(act, exp) { return act <= exp; },
'<': function(act, exp) { return act < exp; },
'>=': function(act, exp) { return act >= exp; },
'>': function(act, exp) { return act > exp; }
}
'=': function(act, exp) { return act === exp; },
'!=': function(act, exp) { return act !== exp; },
'<=': function(act, exp) { return act <= exp; },
'<': function(act, exp) { return act < exp; },
'>=': function(act, exp) { return act >= exp; },
'>': function(act, exp) { return act > exp; },
}
this.applyFilter = function(val) {
}
}
return {
restrict: 'AE',
require: '^FilterGroup',
link: function(scope, el, attrs, filterGroup) {
filterGroup.addFilter()
}
}
})
.controller('MyCtrl', function($scope) {
$scope.columns = [{
name: 'id',
label: 'Id'
}, {
name: 'name',
label: 'Name'
}, {
name: 'age',
label: 'Age'
}]
$scope.phones = phones;
$scope.myFilter = {};
var comparators = {
'=': function(act, exp) { return act === exp },
'!=': function(act, exp) { return act !== exp },
'<=': function(act, exp) { return act <= exp },
'>=': function(act, exp) { return act >= exp },
'<': function(act, exp) { return act < exp },
'>': function(act, exp) { return act > exp },
'in': function(act, exp) { return act.indexof(exp) >= 0 },
'start': function(act, exp) { return act.indexof(exp) === 0 },
}
function compareVal(act, exp, op) {
if(exp === undefined) return true;
var fnCompare = comparators[op];
if(fnCompare)
return fnCompare(act, exp);
// unsupported type
return false;
}
function compareGroup(item, predicates, logOp) {
var ok = true;
for(var key in predicates) {
var pred = predicates[key];
var result = compare(item[key], pred.value, pred.op)
ok = (logOp === '$and') ? (ok && result) : (ok || result)
}
return ok;
}
$scope.filter = function(columns, array, predicate) {
}
})
body {
padding: 60px;
}
th {
cursor: pointer;
}
td {
padding: 2px !important;
}
# Angular super grid #
### first iteration ###
var phones = [
{
"age": 0,
"id": "motorola-xoom-with-wi-fi",
"imageUrl": "img/phones/motorola-xoom-with-wi-fi.0.jpg",
"name": "Motorola XOOM\u2122 with Wi-Fi",
"snippet": "The Next, Next Generation\r\n\r\nExperience the future with Motorola XOOM with Wi-Fi, the world's first tablet powered by Android 3.0 (Honeycomb)."
},
{
"age": 1,
"id": "motorola-xoom",
"imageUrl": "img/phones/motorola-xoom.0.jpg",
"name": "MOTOROLA XOOM\u2122",
"snippet": "The Next, Next Generation\n\nExperience the future with MOTOROLA XOOM, the world's first tablet powered by Android 3.0 (Honeycomb)."
},
{
"age": 2,
"carrier": "AT&T",
"id": "motorola-atrix-4g",
"imageUrl": "img/phones/motorola-atrix-4g.0.jpg",
"name": "MOTOROLA ATRIX\u2122 4G",
"snippet": "MOTOROLA ATRIX 4G the world's most powerful smartphone."
},
{
"age": 3,
"id": "dell-streak-7",
"imageUrl": "img/phones/dell-streak-7.0.jpg",
"name": "Dell Streak 7",
"snippet": "Introducing Dell\u2122 Streak 7. Share photos, videos and movies together. It\u2019s small enough to carry around, big enough to gather around."
},
{
"age": 4,
"carrier": "Cellular South",
"id": "samsung-gem",
"imageUrl": "img/phones/samsung-gem.0.jpg",
"name": "Samsung Gem\u2122",
"snippet": "The Samsung Gem\u2122 brings you everything that you would expect and more from a touch display smart phone \u2013 more apps, more features and a more affordable price."
},
{
"age": 5,
"carrier": "Dell",
"id": "dell-venue",
"imageUrl": "img/phones/dell-venue.0.jpg",
"name": "Dell Venue",
"snippet": "The Dell Venue; Your Personal Express Lane to Everything"
},
{
"age": 6,
"carrier": "Best Buy",
"id": "nexus-s",
"imageUrl": "img/phones/nexus-s.0.jpg",
"name": "Nexus S",
"snippet": "Fast just got faster with Nexus S. A pure Google experience, Nexus S is the first phone to run Gingerbread (Android 2.3), the fastest version of Android yet."
},
{
"age": 7,
"carrier": "Cellular South",
"id": "lg-axis",
"imageUrl": "img/phones/lg-axis.0.jpg",
"name": "LG Axis",
"snippet": "Android Powered, Google Maps Navigation, 5 Customizable Home Screens"
},
{
"age": 8,
"id": "samsung-galaxy-tab",
"imageUrl": "img/phones/samsung-galaxy-tab.0.jpg",
"name": "Samsung Galaxy Tab\u2122",
"snippet": "Feel Free to Tab\u2122. The Samsung Galaxy Tab\u2122 brings you an ultra-mobile entertainment experience through its 7\u201d display, high-power processor and Adobe\u00ae Flash\u00ae Player compatibility."
},
{
"age": 9,
"carrier": "Cellular South",
"id": "samsung-showcase-a-galaxy-s-phone",
"imageUrl": "img/phones/samsung-showcase-a-galaxy-s-phone.0.jpg",
"name": "Samsung Showcase\u2122 a Galaxy S\u2122 phone",
"snippet": "The Samsung Showcase\u2122 delivers a cinema quality experience like you\u2019ve never seen before. Its innovative 4\u201d touch display technology provides rich picture brilliance, even outdoors"
},
{
"age": 10,
"carrier": "Verizon",
"id": "droid-2-global-by-motorola",
"imageUrl": "img/phones/droid-2-global-by-motorola.0.jpg",
"name": "DROID\u2122 2 Global by Motorola",
"snippet": "The first smartphone with a 1.2 GHz processor and global capabilities."
},
{
"age": 11,
"carrier": "Verizon",
"id": "droid-pro-by-motorola",
"imageUrl": "img/phones/droid-pro-by-motorola.0.jpg",
"name": "DROID\u2122 Pro by Motorola",
"snippet": "The next generation of DOES."
},
{
"age": 12,
"carrier": "AT&T",
"id": "motorola-bravo-with-motoblur",
"imageUrl": "img/phones/motorola-bravo-with-motoblur.0.jpg",
"name": "MOTOROLA BRAVO\u2122 with MOTOBLUR\u2122",
"snippet": "An experience to cheer about."
},
{
"age": 13,
"carrier": "T-Mobile",
"id": "motorola-defy-with-motoblur",
"imageUrl": "img/phones/motorola-defy-with-motoblur.0.jpg",
"name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
"snippet": "Are you ready for everything life throws your way?"
},
{
"age": 14,
"carrier": "T-Mobile",
"id": "t-mobile-mytouch-4g",
"imageUrl": "img/phones/t-mobile-mytouch-4g.0.jpg",
"name": "T-Mobile myTouch 4G",
"snippet": "The T-Mobile myTouch 4G is a premium smartphone designed to deliver blazing fast 4G speeds so that you can video chat from practically anywhere, with or without Wi-Fi."
},
{
"age": 15,
"carrier": "US Cellular",
"id": "samsung-mesmerize-a-galaxy-s-phone",
"imageUrl": "img/phones/samsung-mesmerize-a-galaxy-s-phone.0.jpg",
"name": "Samsung Mesmerize\u2122 a Galaxy S\u2122 phone",
"snippet": "The Samsung Mesmerize\u2122 delivers a cinema quality experience like you\u2019ve never seen before. Its innovative 4\u201d touch display technology provides rich picture brilliance,even outdoors"
},
{
"age": 16,
"carrier": "Sprint",
"id": "sanyo-zio",
"imageUrl": "img/phones/sanyo-zio.0.jpg",
"name": "SANYO ZIO",
"snippet": "The Sanyo Zio by Kyocera is an Android smartphone with a combination of ultra-sleek styling, strong performance and unprecedented value."
},
{
"age": 17,
"id": "samsung-transform",
"imageUrl": "img/phones/samsung-transform.0.jpg",
"name": "Samsung Transform\u2122",
"snippet": "The Samsung Transform\u2122 brings you a fun way to customize your Android powered touch screen phone to just the way you like it through your favorite themed \u201cSprint ID Service Pack\u201d."
},
{
"age": 18,
"id": "t-mobile-g2",
"imageUrl": "img/phones/t-mobile-g2.0.jpg",
"name": "T-Mobile G2",
"snippet": "The T-Mobile G2 with Google is the first smartphone built for 4G speeds on T-Mobile's new network. Get the information you need, faster than you ever thought possible."
},
{
"age": 19,
"id": "motorola-charm-with-motoblur",
"imageUrl": "img/phones/motorola-charm-with-motoblur.0.jpg",
"name": "Motorola CHARM\u2122 with MOTOBLUR\u2122",
"snippet": "Motorola CHARM fits easily in your pocket or palm. Includes MOTOBLUR service."
}
]