├── .gitignore ├── Gruntfile.js ├── README.md ├── angular-pagination.js ├── angular-pagination.min.js ├── bower.json ├── examples ├── base │ ├── index.html │ ├── scripts.js │ ├── tpl-1.html │ ├── tpl-2.html │ ├── tpl-3.html │ └── tpl-4.html ├── directive-1 │ ├── index.html │ ├── scripts.js │ └── tpl-4.html └── directive-2 │ ├── index.html │ ├── scripts.js │ └── tpl-4.html ├── license.txt ├── package.json └── src └── pagination.js /.gitignore: -------------------------------------------------------------------------------- 1 | .temp 2 | .idea 3 | node_modules 4 | bower_components -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | 6 | banner: '/*\n' + 7 | ' <%= pkg.name %> v<%= pkg.version %>\n' + 8 | ' <%= pkg.homepage %>\n' + 9 | '*/\n', 10 | 11 | clean: { 12 | working: { 13 | src: ['angular-pagination.*'] 14 | } 15 | }, 16 | 17 | uglify: { 18 | js: { 19 | src: ['src/pagination.js'], 20 | dest: 'angular-pagination.min.js', 21 | options: { 22 | banner: '<%= banner %>' 23 | } 24 | } 25 | }, 26 | 27 | concat: { 28 | js: { 29 | options: { 30 | banner: '<%= banner %>', 31 | stripBanners: true 32 | }, 33 | src: ['src/pagination.js'], 34 | dest: 'angular-pagination.js' 35 | } 36 | } 37 | }); 38 | 39 | grunt.loadNpmTasks('grunt-contrib-clean'); 40 | grunt.loadNpmTasks('grunt-contrib-copy'); 41 | grunt.loadNpmTasks('grunt-contrib-uglify'); 42 | grunt.loadNpmTasks('grunt-contrib-concat'); 43 | 44 | grunt.registerTask('default', ['clean', 'concat', 'uglify']); 45 | }; 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Angular Pagination 2 | 3 | ## About 4 | 5 | **Angular Pagination** is a module for the [AngularJS](http://angularjs.org/) framework. 6 | 7 | ## Usage 8 | Simple example: 9 | ```js 10 | angular 11 | 12 | .module('app', ['angularPagination']) 13 | 14 | .controller('AppController', function($scope, Pagination) { 15 | var pagination = $scope.pagination = Pagination.create({ 16 | itemsPerPage: 10, 17 | itemsCount: 100, 18 | maxNumbers: 5 19 | }); 20 | 21 | pagination.onChange = function(page) { 22 | console.info('page=', page); 23 | }; 24 | }); 25 | ``` 26 | ```html 27 |
28 | 33 |
34 | ``` 35 | See [demo](http://nervgh.github.io/pages/angular-pagination/examples/base) of full functionality 36 | 37 | 38 | ## Demos 39 | 1. [Example of full functionality](http://nervgh.github.io/pages/angular-pagination/examples/base) 40 | 2. [Example of directive 1](http://nervgh.github.io/pages/angular-pagination/examples/directive-1) 41 | 3. [Example of directive 2](http://nervgh.github.io/pages/angular-pagination/examples/directive-2) 42 | -------------------------------------------------------------------------------- /angular-pagination.js: -------------------------------------------------------------------------------- 1 | /* 2 | angular-pagination v0.2.2 3 | https://github.com/nervgh/angular-pagination 4 | */ 5 | 6 | 7 | angular 8 | 9 | 10 | .module('angularPagination', []) 11 | 12 | 13 | .value('paginationOptions', { 14 | itemsPerPage: 10, 15 | itemsCount: 100, 16 | maxNumbers: 5, 17 | startPage: 1, 18 | currentPage: 1 19 | }) 20 | 21 | 22 | .factory('Pagination', ['paginationOptions', function(paginationOptions) { 23 | /** 24 | * Creates new pagination object 25 | * @param {Object} options 26 | * @constructor 27 | */ 28 | function Pagination(options) { 29 | var defaults = angular.copy(paginationOptions); 30 | angular.extend(this, defaults, options); 31 | this.endPage = null; 32 | this.pages = []; 33 | this._lastPage = null; 34 | this.setCurrent(this.currentPage); 35 | } 36 | 37 | /** 38 | * Sets current page 39 | * @param {Number} page 40 | */ 41 | Pagination.prototype.setCurrent = function(page) { 42 | this.endPage = Math.ceil(this.itemsCount / this.itemsPerPage); 43 | this.currentPage = this._fixPage(Math.floor(page)); 44 | this._change(this.currentPage); 45 | this._updatePages(); 46 | }; 47 | /** 48 | * Returns "true" if page is current 49 | * @param {Number} page 50 | * @returns {Boolean} 51 | */ 52 | Pagination.prototype.isCurrent = function(page) { 53 | return this.currentPage === page; 54 | }; 55 | /** 56 | * Returns "true" if page inside of range 57 | * @param {Number} page 58 | * @returns {boolean} 59 | */ 60 | Pagination.prototype.inRange = function(page) { 61 | return this.startPage <= page && this.endPage >= page; 62 | }; 63 | /** 64 | * Returns "true" if page is first 65 | * @param {Number} page 66 | * @returns {Boolean} 67 | */ 68 | Pagination.prototype.isFirst = function(page) { 69 | return this.startPage === page; 70 | }; 71 | /** 72 | * Returns "true" if page is last 73 | * @param {Number} page 74 | * @returns {Boolean} 75 | */ 76 | Pagination.prototype.isLast = function(page) { 77 | return this.endPage === page; 78 | }; 79 | /** 80 | * Callback. Called when page changed 81 | * @param {Number} page 82 | */ 83 | Pagination.prototype.onChange = function(page) { 84 | }; 85 | /** 86 | * Fixes number of page if it outside range 87 | * @param {Number} page 88 | * @returns {number} 89 | * @private 90 | */ 91 | Pagination.prototype._fixPage = function(page) { 92 | page = Math.min(page, this.endPage); 93 | page = Math.max(page, this.startPage); 94 | return page; 95 | }; 96 | /** 97 | * Calls "onChange" if number of page was changed 98 | * @param {Number} page 99 | * @private 100 | */ 101 | Pagination.prototype._change = function(page) { 102 | if (this._lastPage !== page) { 103 | this._lastPage = page; 104 | this.onChange(page); 105 | } 106 | }; 107 | /** 108 | * Updates array of pages 109 | * @private 110 | */ 111 | Pagination.prototype._updatePages = function() { 112 | var delta = Math.floor(this.maxNumbers / 2); 113 | var start = Math.max(this.currentPage - delta, this.startPage); 114 | var end = Math.min(start + this.maxNumbers - 1, this.endPage); 115 | 116 | start = this.endPage === end ? end - (this.maxNumbers - 1) : start; 117 | start = Math.max(start, this.startPage); 118 | this.pages.length = 0; 119 | 120 | for(var i = start; i <= end; i++) { 121 | this.pages.push(i); 122 | } 123 | }; 124 | /** 125 | * Creates and returns a pagination object 126 | * @param {Object} options 127 | * @returns {Pagination} 128 | */ 129 | Pagination.create = function(options) { 130 | return new Pagination(options); 131 | }; 132 | 133 | return Pagination; 134 | }]); 135 | -------------------------------------------------------------------------------- /angular-pagination.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | angular-pagination v0.2.2 3 | https://github.com/nervgh/angular-pagination 4 | */ 5 | angular.module("angularPagination",[]).value("paginationOptions",{itemsPerPage:10,itemsCount:100,maxNumbers:5,startPage:1,currentPage:1}).factory("Pagination",["paginationOptions",function(a){function b(b){var c=angular.copy(a);angular.extend(this,c,b),this.endPage=null,this.pages=[],this._lastPage=null,this.setCurrent(this.currentPage)}return b.prototype.setCurrent=function(a){this.endPage=Math.ceil(this.itemsCount/this.itemsPerPage),this.currentPage=this._fixPage(Math.floor(a)),this._change(this.currentPage),this._updatePages()},b.prototype.isCurrent=function(a){return this.currentPage===a},b.prototype.inRange=function(a){return this.startPage<=a&&this.endPage>=a},b.prototype.isFirst=function(a){return this.startPage===a},b.prototype.isLast=function(a){return this.endPage===a},b.prototype.onChange=function(){},b.prototype._fixPage=function(a){return a=Math.min(a,this.endPage),a=Math.max(a,this.startPage)},b.prototype._change=function(a){this._lastPage!==a&&(this._lastPage=a,this.onChange(a))},b.prototype._updatePages=function(){var a=Math.floor(this.maxNumbers/2),b=Math.max(this.currentPage-a,this.startPage),c=Math.min(b+this.maxNumbers-1,this.endPage);b=this.endPage===c?c-(this.maxNumbers-1):b,b=Math.max(b,this.startPage),this.pages.length=0;for(var d=b;c>=d;d++)this.pages.push(d)},b.create=function(a){return new b(a)},b}]); -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-pagination", 3 | "version": "0.2.2", 4 | "main": "angular-pagination.js", 5 | "homepage": "https://github.com/nervgh/angular-pagination", 6 | "ignore": ["examples"], 7 | "dependencies": { 8 | "angular": ">=1.1.5" 9 | }, 10 | "keywords": [ 11 | "angular", 12 | "pagination" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/base/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Pagination 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 36 |
37 |
38 |

Pagination

39 |
40 |
41 | itemsPerPage:
42 | itemsCount:
43 | maxNumbers:
44 | startPage:
45 |
46 |
47 |
Page:  / 
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 | -------------------------------------------------------------------------------- /examples/base/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular 4 | 5 | 6 | .module('app', ['angularPagination']) 7 | 8 | 9 | .controller('AppController', function($scope, Pagination) { 10 | var pagination = $scope.pagination = Pagination.create({ 11 | itemsPerPage: 10, 12 | itemsCount: 100, 13 | maxNumbers: 5 14 | }); 15 | 16 | pagination.onChange = function(page) { 17 | console.info('page=', page); 18 | }; 19 | 20 | pagination.setCurrent(1); 21 | 22 | $scope.$watchCollection('[pagination.startPage, pagination.maxNumbers, pagination.itemsCount, pagination.itemsPerPage]', function() { 23 | pagination.setCurrent(pagination.currentPage); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/base/tpl-1.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/base/tpl-2.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/base/tpl-3.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/base/tpl-4.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/directive-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Pagination 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 36 |
37 |
38 |

Pagination

39 |
40 |
41 | itemsPerPage:
42 | itemsCount:
43 | maxNumbers:
44 | startPage:
45 |
46 |
47 |
Page:  / 
48 |
49 |
50 |
51 |
52 |
53 | 54 | -------------------------------------------------------------------------------- /examples/directive-1/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular 4 | 5 | 6 | .module('app', ['angularPagination']) 7 | 8 | 9 | .controller('AppController', function($scope, Pagination) { 10 | var pagination = $scope.pagination = Pagination.create({ 11 | itemsPerPage: 10, 12 | itemsCount: 100, 13 | maxNumbers: 5 14 | }); 15 | 16 | pagination.onChange = function(page) { 17 | console.info('page=', page); 18 | }; 19 | }) 20 | 21 | 22 | .directive('ngPagination', function() { 23 | return { 24 | templateUrl: 'tpl-4.html', 25 | link: function(scope, element, attributes) { 26 | var p = scope.$eval(attributes.ngPagination); 27 | 28 | function watcher() { 29 | return [p.startPage, p.maxNumbers, p.itemsCount, p.itemsPerPage].toString(); 30 | } 31 | function handler() { 32 | p.setCurrent(p.currentPage); 33 | } 34 | 35 | scope.$watch(watcher, handler); 36 | } 37 | }; 38 | }); -------------------------------------------------------------------------------- /examples/directive-1/tpl-4.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/directive-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Pagination 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 36 |
37 |
38 |

Pagination

39 |
40 |
41 |
42 |
43 |
44 |
45 | 46 | -------------------------------------------------------------------------------- /examples/directive-2/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular 4 | 5 | 6 | .module('app', ['angularPagination']) 7 | 8 | 9 | .controller('AppController', function($scope) { 10 | $scope.onPageChange = function(page) { 11 | console.info('page=', page); 12 | }; 13 | }) 14 | 15 | 16 | .directive('ngPagination', ['Pagination', function(Pagination) { 17 | return { 18 | templateUrl: 'tpl-4.html', 19 | link: function(scope, element, attributes) { 20 | var cb = scope.$eval(attributes.ngPagination) || angular.noop; 21 | var pagination = scope.pagination = Pagination.create({ 22 | itemsPerPage: 10, 23 | itemsCount: 100, 24 | maxNumbers: 5, 25 | onChange: cb 26 | }); 27 | pagination.setCurrent(1); 28 | } 29 | }; 30 | }]); -------------------------------------------------------------------------------- /examples/directive-2/tpl-4.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 nerv. https://github.com/nervgh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-pagination", 3 | "version": "0.2.2", 4 | "homepage": "https://github.com/nervgh/angular-pagination", 5 | "description": "Angular Pagination is a module for the AngularJS framework", 6 | "author": { 7 | "name": "nerv", 8 | "url": "https://github.com/nervgh" 9 | }, 10 | "dependencies": { 11 | "coffee-script": "~1.6.2", 12 | "grunt-contrib-copy": "~0.4.1", 13 | "grunt-contrib-clean": "~0.4.0", 14 | "grunt-contrib-concat": "~0.3.0", 15 | "grunt-contrib-uglify": "~0.2.1", 16 | "grunt": "~0.4.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/pagination.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular 4 | 5 | 6 | .module('angularPagination', []) 7 | 8 | 9 | .value('paginationOptions', { 10 | itemsPerPage: 10, 11 | itemsCount: 100, 12 | maxNumbers: 5, 13 | startPage: 1, 14 | currentPage: 1 15 | }) 16 | 17 | 18 | .factory('Pagination', ['paginationOptions', function(paginationOptions) { 19 | /** 20 | * Creates new pagination object 21 | * @param {Object} options 22 | * @constructor 23 | */ 24 | function Pagination(options) { 25 | var defaults = angular.copy(paginationOptions); 26 | angular.extend(this, defaults, options); 27 | this.endPage = null; 28 | this.pages = []; 29 | this._lastPage = null; 30 | this.setCurrent(this.currentPage); 31 | } 32 | 33 | /** 34 | * Sets current page 35 | * @param {Number} page 36 | */ 37 | Pagination.prototype.setCurrent = function(page) { 38 | this.endPage = Math.ceil(this.itemsCount / this.itemsPerPage); 39 | this.currentPage = this._fixPage(Math.floor(page)); 40 | this._change(this.currentPage); 41 | this._updatePages(); 42 | }; 43 | /** 44 | * Returns "true" if page is current 45 | * @param {Number} page 46 | * @returns {Boolean} 47 | */ 48 | Pagination.prototype.isCurrent = function(page) { 49 | return this.currentPage === page; 50 | }; 51 | /** 52 | * Returns "true" if page inside of range 53 | * @param {Number} page 54 | * @returns {boolean} 55 | */ 56 | Pagination.prototype.inRange = function(page) { 57 | return this.startPage <= page && this.endPage >= page; 58 | }; 59 | /** 60 | * Returns "true" if page is first 61 | * @param {Number} page 62 | * @returns {Boolean} 63 | */ 64 | Pagination.prototype.isFirst = function(page) { 65 | return this.startPage === page; 66 | }; 67 | /** 68 | * Returns "true" if page is last 69 | * @param {Number} page 70 | * @returns {Boolean} 71 | */ 72 | Pagination.prototype.isLast = function(page) { 73 | return this.endPage === page; 74 | }; 75 | /** 76 | * Callback. Called when page changed 77 | * @param {Number} page 78 | */ 79 | Pagination.prototype.onChange = function(page) { 80 | }; 81 | /** 82 | * Fixes number of page if it outside range 83 | * @param {Number} page 84 | * @returns {number} 85 | * @private 86 | */ 87 | Pagination.prototype._fixPage = function(page) { 88 | page = Math.min(page, this.endPage); 89 | page = Math.max(page, this.startPage); 90 | return page; 91 | }; 92 | /** 93 | * Calls "onChange" if number of page was changed 94 | * @param {Number} page 95 | * @private 96 | */ 97 | Pagination.prototype._change = function(page) { 98 | if (this._lastPage !== page) { 99 | this._lastPage = page; 100 | this.onChange(page); 101 | } 102 | }; 103 | /** 104 | * Updates array of pages 105 | * @private 106 | */ 107 | Pagination.prototype._updatePages = function() { 108 | var delta = Math.floor(this.maxNumbers / 2); 109 | var start = Math.max(this.currentPage - delta, this.startPage); 110 | var end = Math.min(start + this.maxNumbers - 1, this.endPage); 111 | 112 | start = this.endPage === end ? end - (this.maxNumbers - 1) : start; 113 | start = Math.max(start, this.startPage); 114 | this.pages.length = 0; 115 | 116 | for(var i = start; i <= end; i++) { 117 | this.pages.push(i); 118 | } 119 | }; 120 | /** 121 | * Creates and returns a pagination object 122 | * @param {Object} options 123 | * @returns {Pagination} 124 | */ 125 | Pagination.create = function(options) { 126 | return new Pagination(options); 127 | }; 128 | 129 | return Pagination; 130 | }]); 131 | --------------------------------------------------------------------------------