var app = angular.module('myApp', ['ngGrid']);

app.controller('Ctrl', function($scope) {
    
    $scope.add = function() {
      console.log("add todo was clicked...");
      $scope.todos.push({
        "name" : $scope.name,
        "estimate" : 100,
        "done" : false,
        "created_at" : new Date(),
        "update-at" : ""
      });
    };
    
    $scope.todos = [
        {
        "name": "inicio",
        "estimate": 1,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "asdfasfd",
        "estimate": 2,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "hjjhjh",
        "estimate": 3,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "ytrt rtyuty rtuy",
        "estimate": 4,
        "done": false,
        "created_at": "2012-10-03",
        "update_at": ""},
    {
        "name": "vbbv ghjghj",
        "estimate": 5,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "ghfg",
        "estimate": 6,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "iouioiuo",
        "estimate": 7,
        "done": true,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "tyutyu",
        "estimate": 8,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "dfdf",
        "estimate": 9,
        "done": true,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "vbnvb",
        "estimate": 10,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "fgfg",
        "estimate": 11,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "asdfasfd",
        "estimate": 12,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "hjjhjh",
        "estimate": 13,
        "done": false,
        "created_at": "2012-01-03",
        "update_at": ""},
    {
        "name": "ytrt rtyuty rtuy",
        "estimate": 14,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "vbbv ghjghj",
        "estimate": 15,
        "done": false,
        "created_at": "2012-03-03"},
    {
        "name": "ghfg",
        "estimate": 16,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "iouioiuo",
        "estimate": 17,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "tyutyu",
        "estimate": 18,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "dfdf",
        "estimate": 19,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "vbnvb",
        "estimate": 20,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "fgfg",
        "estimate": 201,
        "done": false,
        "created_at": "2012-05-03"},
    {
        "name": "asdfasfd",
        "estimate": 21,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "hjjhjh",
        "estimate": 22,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "ytrt rtyuty rtuy",
        "estimate": 23,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "vbbv ghjghj",
        "estimate": 24,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "ghfg",
        "estimate": 25,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "iouioiuo",
        "estimate": 26,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "tyutyu",
        "estimate": 27,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "dfdf",
        "estimate": 28,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "vbnvb",
        "estimate": 29,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "fgfg",
        "estimate": 299,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "asdfasfd",
        "estimate": 30,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "hjjhjh",
        "estimate": 31,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "ytrt ry rtuy",
        "estimate": 32,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "vbbv ghjghj",
        "estimate": 33,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "ghfg",
        "estimate": 34,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "iouioiuo",
        "estimate": 35,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "tyutyu",
        "estimate": 36,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "dfdf",
        "estimate": 37,
        "done": true,
        "created_at": "2012-01-03"},
    {
        "name": "kjhkh",
        "estimate": 38,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "kjhkhj",
        "estimate": 39,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "jkhkhk",
        "estimate": 40,
        "done": false,
        "created_at": "2012-01-03"},
    {
        "name": "final",
        "estimate": 41,
        "done": false,
        "created_at": "2012-01-03"}
    ];
});
(function(angular) {
  var ngGridModule = angular.module('ngGrid', []); 
  
  // the skip filter
  ngGridModule.filter('skip', function() {
      return function(array, skipAt) {
          return array.slice(skipAt);
      };
  });
  
  ngGridModule.filter('eval', function() {
      return function(expression) {
          return this.$eval(expression);
      };
  });

  ngGridModule.filter('length', function() {
      return function(list) {
          return list.length;
      };
  });

  ngGridModule.filter('lastPage', function() {
      return function(list, limit) {
          return Math.ceil(list.length / limit);
      };
  });
  
  ngGridModule.filter('equal', function() {
      return function(a, b, klass) {
          return a === b ? klass : '';
      };
  });
  
  ngGridModule.filter('toPages', function() {
      return function(length) {
          if(!length) return [];
          return new Array(length);
      };
  });
  
  // the row filter
  ngGridModule.filter('rowFilter', function() {
    return function(items, row, term) { 
      if (items === undefined) {
        return;         
      }
      var arrayToReturn = [];
      for (var i=0; i<items.length; i++) {
        if (items[i][row] == term) {
          arrayToReturn.push(items[i]);
        }        
      }
      return arrayToReturn;    
    };
  });

  // the main directive: ngGrid
  ngGridModule.directive('ngGrid',  function($compile, $filter) {
    return {
      compile: function compile(element, attrs) {
            
        var 
                index = 0,
                tr = element.children('tbody').children('tr'),
                sourceExpression     = tr.attr('ng-repeat').match(/^\s*(.+)\s+in\s+(.*)\s*$/),
                baseExpression = sourceExpression[2],
                itemExpression = sourceExpression[1];
                    
        tr.attr('ng-repeat', itemExpression + ' in ngGridSortPagination.expression | eval | skip:ngGridSortPagination.skipAt | orderBy:ngGridSortPagination.predicate:ngGridSortPagination.reverse | limitTo:ngGridSortPagination.limit');
            
        var header = [],
        filter_hash = {};
            
        angular.forEach(tr.children('td'), function(elm) {
            var column = angular.element(elm),
                exp = column.html().replace(/[{}\s]/g, ""),
                name = exp.split(/\.(.+)?/)[1].split(/\|/)[0],
                filter = exp.split(/\.(.+)?/)[1].split(/\|/)[1],
                filterAttrib = (!filter) ? "" : ' filter="' + filter + '"',
                title = column.attr('title') || name;

            // build up a list of all header elements
            header.push({
              name: name,
              title: title,
              index: index
            });
                
            if(name) {
              filter_hash[name.toLowerCase()] = index;
              filter_hash[name] = index;
            }

            column.attr('title', null);
            index ++;
        });
        element.prepend('<thead>' +
          '<th ng-repeat="head in ngGridSortPagination.header" ng-click="sort(head.index)">' +
            '<i ng-class="{\'icon-arrow-up\': ngGridSortPagination.predicate==head.name && ngGridSortPagination.reverse, \'icon-arrow-down\': ngGridSortPagination.predicate==head.name && !ngGridSortPagination.reverse}" ></i>' +
            '<a>{{head.title}}</a>' +
          '</th>' +
        '</thead>');

        return {
            pre: function preLink(scope, linkElement) {
                var ngGridSortPagination = {
                  expression: baseExpression,
                  limit     : 15,
                  page      : 1,
                  skipAt    : 15, // muss noch umgestellt werden
                  header    : header
                  
                  
                },
                listExpression = baseExpression;
                scope.ngGridSortPagination  = ngGridSortPagination;

                scope.$watch('ngGridSortPagination.filter', function() {
                  if (ngGridSortPagination.filter) {
                    var filterExpression;
                    if(angular.lowercase(ngGridSortPagination.filter).indexOf(":") !== -1) {
                      var query = ngGridSortPagination.filter.split(":"),
                          row = query[0].replace(" ", "_"),
                          filter = query[1];
                      if (row in filter_hash) {  											
                        var head = ngGridSortPagination.header[filter_hash[row]];
                        if (filter) {
                          filterExpression = '| rowFilter:' + head.name + ':' + filter;
                          console.log(filterExpression);
                         }
                         baseExpression = baseExpression + filterExpression;												
                      }                          
                    }  else {
                      console.log('any filter');
                    }
                  }
                });
    
                var pageSize = 
                    '<select ng-model="ngGridSortPagination.limit">' +
                      '<option  value="15" selected="selected">15</option>' +
                      '<option  value="30">30</option>' +
                      '<option  value="60">60</option>' +
                    '</select>';
                element.before($compile(pageSize)(scope));

							var filter =                                               
								'<input style="float:right; width: 200px" ng-model="ngGridSortPagination.filter" placeholder="Filter..." name="filter" />';
							element.before($compile(filter)(scope));
							
							var debugOutput =                     
								'<pre>header = {{header | json}}</pre>' +
								'<pre>pagination = {{ngGridSortPagination | json}}</pre>';
							element.after($compile(debugOutput)(scope));
							
							var footer =
								'<div style="float: left; padding-top: 10px;">' +
									'<strong>Total items: {{ngGridSortPagination.expression | eval | length}}</strong>' +
								'</div>' +
								'<div class="pagination pagination-right">' +
									'<ul>' +
										'<li ng-class="ngGridSortPagination.page | equal:1:\'disabled\'">' +
											'<a ng-click="prev()">Prev</a>' +
										'</li>' +
										'<li ng-repeat="index in ngGridSortPagination.expression | eval | lastPage:ngGridSortPagination.limit | toPages" ng-class="{active: ngGridSortPagination.page==index}">' +
											'<a ng-click="page($index + 1)">{{$index + 1}}</a></li>' +
										'</li>' +
                    '<li ng-class="ngGridSortPagination.page | equal:1:\'disabled\'">' +
                      '<a ng-click="next()">Next</a>' +
										'</li>' +
									'</ul>' +
								'</div>';                      
                element.after($compile(footer)(scope));
                    
                scope.sort = function(index) {
                  var head = header[index];
                  // if the grid is already sorted by this head and not in reverse mode:
                  ngGridSortPagination.reverse = (ngGridSortPagination.predicate === head.name) && ! ngGridSortPagination.reverse;
                  // set sorting to this head
                  ngGridSortPagination.predicate = head.name;
                };
                    
                scope.prev = function() {
                    scope.page(ngGridSortPagination.page - 1);
                };
                    
                scope.next = function() {
                    scope.page(ngGridSortPagination.page + 1);
                };
                    
                scope.page = function(index) {
                    ngGridSortPagination.page = index;
                    ngGridSortPagination.skipAt = ((ngGridSortPagination.page - 1) * ngGridSortPagination.limit);
                };
   
            }
        };
      }
    };
});
})(window.angular);
<!DOCTYPE html>
<html ng-app="myApp">
  <head lang="en">
    <meta charset="utf-8">
    <title>Bootstrap Table Directive</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
    <script src="app.js"></script>
    <script src="controller.js"></script>
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap-combined.min.css"
    rel="stylesheet">
    <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/js/bootstrap.min.js"></script>
  </head> 
  <body ng-controller="Ctrl">
    <div class="span12">
      <form>
        <legend>Add Todo</legend>
        <label>Todo title</label>
        <input type="text" class="input-medium" placeholder="Add Todo.." ng-model="name"> 
        <label>Todo date</label>
        <input type="text" class="input-medium" placeholder="Add Todo.." ng-model="name"> 
        <br/>
        <button type="submit" class="btn">Submit</button>
      </form>      
      <table class="table table-bordered table-striped" ng-grid>  		
    			<legend>Todo List</legend>
    		    	<tr ng-repeat="todo in todos">
    		      	<td title="Name">{{todo.name}}</td>
    		      	<td title="Estimate">{{todo.estimate}}</td>
    		      	<td title="Name">{{todo.created_at}}</td>
    		      	<td title="Estimate">{{todo.updated_at}}</td>										
    		    	</tr>		  
    	</table>
    </div>
    
  </body>

</html>