<!DOCTYPE html>
<html ng-app="app">

  <head>
    <link data-require="bootstrap-css@*" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
    <script data-require="jquery@1.8.2" data-semver="1.8.2" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.js"></script>
    <script data-require="angular.js@1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
    <script data-require="ui-bootstrap@0.4.0" data-semver="0.4.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.4.0.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <h1>paginated list</h1>

    <p>Use the input to filter by browser. The list will update on hitting <code>enter</code> or by leaving the field. Changing the filter should reset the pagination.</p>
    
    <div ng-controller='MyController'>
      <input type="text" name="browser" id="browser" ng-model="query.browser" ng-model-blur placeholder="browser" />
      <pre>{{query}}</pre>

      <hr>

      <article ng-repeat="item in pagedItems">
        <pre>{{item}}</pre>
      </article>

      <div class="clearfix">
        <span class="pull-left">showing {{start}} to {{end}} of {{filteredItems.length}}<span ng-show="data.length != filteredItems.length"> (from {{data.length}})</span></span>

        <pagination class="pagination-right pagination-small" style="margin:0" num-pages="numOfPages" current-page="currentPage" max-size="maxSize" boundary-links="true"></pagination>
      </div>
    </div>
  </body>

</html>
// Code goes here

var app = angular.module('app', ['ui.bootstrap']);

function MyController($scope, $http, $filter) {
  // default values for pagination and filtering
  $scope.pageSize = 5;
  $scope.maxSize = 5;
  $scope.start = 0;
  $scope.end = 0;
  $scope.currentPage = 0;
  $scope.numOfPages = 0;
  $scope.filteredItems = [];
  $scope.startItems = [];
  $scope.pagedItems = [];
  $scope.data = null;
  $scope.query = {browser: ""};
  
  // get the data
  $http.get('data.json')
    .success(function (data) {
      // set the data
      $scope.data = data.aaData;
    });
  
  // when the data is altered, filter the items and set the page
  $scope.$watch('data', function (data, old) {
    $scope.filteredItems = $filter('filter')(data, $scope.query);
    if (old === null) setPage();
  });

  // when the query value changes, refilter the data
  $scope.$watch('query|json', function () {
    $scope.filteredItems = $filter('filter')($scope.data, $scope.query);
  });
  
  // set the pagination for the filtered items
  function setPage() {
    $scope.start = ($scope.currentPage - 1) * $scope.pageSize + ($scope.filteredItems.length ? 1 : 0);
    $scope.startItems = $filter('startFrom')($scope.filteredItems, $scope.start - 1);
  }
  
  // when the current page is changed by the pagination control, update the list of items
  $scope.$watch('currentPage', function (page) {
    setPage();
  });

  // when the filtered items are set, recalculate the number of pages
  $scope.$watch('filteredItems', function (items, old) {
    $scope.currentPage = 1;
    $scope.numOfPages = Math.ceil(items.length / $scope.pageSize);
  });
  
  // when the page start is changed, update the list of paged items
  $scope.$watch('startItems', function (items) {
    $scope.pagedItems = $filter('limitTo')(items, $scope.pageSize);
    $scope.end = ($scope.currentPage - 1) * $scope.pageSize + $scope.pagedItems.length;
  });
}

// angular directive to change default behavior from processing input change immediately to on blur or enter
app.directive('ngModelBlur', function () {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, elm, attr, ngModelCtrl) {
      if (attr.type === 'radio' || attr.type === 'checkbox') { return; }

      elm.unbind('input').unbind('keydown').unbind('change');
      elm.bind('blur keydown', function (e) {
        if (e.type === 'keydown' && e.which !== 13) { return; }

        scope.$apply(function () {
          ngModelCtrl.$setViewValue(elm.val());
        });         
      });
    }
  };
});

// angular filter to take array items starting from provided index
app.filter('startFrom', function () {
  return function (input, start) {
    if (angular.isArray(input)) {
      var st = parseInt(start, 10);
      if (isNaN(st)) st = 0;
      return input.slice(st);
    }
    return input;
  };
});
/* Styles go here */

body {
  margin: 1em;
}
{
  "aaData": [
    {
      "engine": "Trident",
      "browser": "Internet Explorer 4.0",
      "platform": {
        "inner": "Win 95+",
        "details": [
          "4",
          "X"
        ]
      }
    },
    {
      "engine": "Trident",
      "browser": "Internet Explorer 5.0",
      "platform": {
        "inner": "Win 95+",
        "details": [
          "5",
          "C"
        ]
      }
    },
    {
      "engine": "Trident",
      "browser": "Internet Explorer 5.5",
      "platform": {
        "inner": "Win 95+",
        "details": [
          "5.5",
          "A"
        ]
      }
    },
    {
      "engine": "Trident",
      "browser": "Internet Explorer 6",
      "platform": {
        "inner": "Win 98+",
        "details": [
          "6",
          "A"
        ]
      }
    },
    {
      "engine": "Trident",
      "browser": "Internet Explorer 7",
      "platform": {
        "inner": "Win XP SP2+",
        "details": [
          "7",
          "A"
        ]
      }
    },
    {
      "engine": "Trident",
      "browser": "AOL browser (AOL desktop)",
      "platform": {
        "inner": "Win XP",
        "details": [
          "6",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Firefox 1.0",
      "platform": {
        "inner": "Win 98+ / OSX.2+",
        "details": [
          "1.7",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Firefox 1.5",
      "platform": {
        "inner": "Win 98+ / OSX.2+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Firefox 2.0",
      "platform": {
        "inner": "Win 98+ / OSX.2+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Firefox 3.0",
      "platform": {
        "inner": "Win 2k+ / OSX.3+",
        "details": [
          "1.9",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Camino 1.0",
      "platform": {
        "inner": "OSX.2+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Camino 1.5",
      "platform": {
        "inner": "OSX.3+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Netscape 7.2",
      "platform": {
        "inner": "Win 95+ / Mac OS 8.6-9.2",
        "details": [
          "1.7",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Netscape Browser 8",
      "platform": {
        "inner": "Win 98SE+",
        "details": [
          "1.7",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Netscape Navigator 9",
      "platform": {
        "inner": "Win 98+ / OSX.2+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.0",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.1",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.1,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.2",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.2,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.3",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.3,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.4",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.4,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.5",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.5,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.6",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          1.6,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.7",
      "platform": {
        "inner": "Win 98+ / OSX.1+",
        "details": [
          1.7,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Mozilla 1.8",
      "platform": {
        "inner": "Win 98+ / OSX.1+",
        "details": [
          1.8,
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Seamonkey 1.1",
      "platform": {
        "inner": "Win 98+ / OSX.2+",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Gecko",
      "browser": "Epiphany 2.20",
      "platform": {
        "inner": "Gnome",
        "details": [
          "1.8",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "Safari 1.2",
      "platform": {
        "inner": "OSX.3",
        "details": [
          "125.5",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "Safari 1.3",
      "platform": {
        "inner": "OSX.3",
        "details": [
          "312.8",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "Safari 2.0",
      "platform": {
        "inner": "OSX.4+",
        "details": [
          "419.3",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "Safari 3.0",
      "platform": {
        "inner": "OSX.4+",
        "details": [
          "522.1",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "OmniWeb 5.5",
      "platform": {
        "inner": "OSX.4+",
        "details": [
          "420",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "iPod Touch / iPhone",
      "platform": {
        "inner": "iPod",
        "details": [
          "420.1",
          "A"
        ]
      }
    },
    {
      "engine": "Webkit",
      "browser": "S60",
      "platform": {
        "inner": "S60",
        "details": [
          "413",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 7.0",
      "platform": {
        "inner": "Win 95+ / OSX.1+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 7.5",
      "platform": {
        "inner": "Win 95+ / OSX.2+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 8.0",
      "platform": {
        "inner": "Win 95+ / OSX.2+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 8.5",
      "platform": {
        "inner": "Win 95+ / OSX.2+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 9.0",
      "platform": {
        "inner": "Win 95+ / OSX.3+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 9.2",
      "platform": {
        "inner": "Win 88+ / OSX.3+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera 9.5",
      "platform": {
        "inner": "Win 88+ / OSX.3+",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Opera for Wii",
      "platform": {
        "inner": "Wii",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Nokia N800",
      "platform": {
        "inner": "N800",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Presto",
      "browser": "Nintendo DS browser",
      "platform": {
        "inner": "Nintendo DS",
        "details": [
          "8.5",
          "C/A<sup>1</sup>"
        ]
      }
    },
    {
      "engine": "KHTML",
      "browser": "Konqureror 3.1",
      "platform": {
        "inner": "KDE 3.1",
        "details": [
          "3.1",
          "C"
        ]
      }
    },
    {
      "engine": "KHTML",
      "browser": "Konqureror 3.3",
      "platform": {
        "inner": "KDE 3.3",
        "details": [
          "3.3",
          "A"
        ]
      }
    },
    {
      "engine": "KHTML",
      "browser": "Konqureror 3.5",
      "platform": {
        "inner": "KDE 3.5",
        "details": [
          "3.5",
          "A"
        ]
      }
    },
    {
      "engine": "Tasman",
      "browser": "Internet Explorer 4.5",
      "platform": {
        "inner": "Mac OS 8-9",
        "details": [
          "-",
          "X"
        ]
      }
    },
    {
      "engine": "Tasman",
      "browser": "Internet Explorer 5.1",
      "platform": {
        "inner": "Mac OS 7.6-9",
        "details": [
          "1",
          "C"
        ]
      }
    },
    {
      "engine": "Tasman",
      "browser": "Internet Explorer 5.2",
      "platform": {
        "inner": "Mac OS 8-X",
        "details": [
          "1",
          "C"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "NetFront 3.1",
      "platform": {
        "inner": "Embedded devices",
        "details": [
          "-",
          "C"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "NetFront 3.4",
      "platform": {
        "inner": "Embedded devices",
        "details": [
          "-",
          "A"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "Dillo 0.8",
      "platform": {
        "inner": "Embedded devices",
        "details": [
          "-",
          "X"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "Links",
      "platform": {
        "inner": "Text only",
        "details": [
          "-",
          "X"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "Lynx",
      "platform": {
        "inner": "Text only",
        "details": [
          "-",
          "X"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "IE Mobile",
      "platform": {
        "inner": "Windows Mobile 6",
        "details": [
          "-",
          "C"
        ]
      }
    },
    {
      "engine": "Misc",
      "browser": "PSP browser",
      "platform": {
        "inner": "PSP",
        "details": [
          "-",
          "C"
        ]
      }
    },
    {
      "engine": "Other browsers",
      "browser": "All others",
      "platform": {
        "inner": "-",
        "details": [
          "-",
          "U"
        ]
      }
    }
  ]
}