From a023d082b3e42697d3d4dbcf9b62b58a0429da03 Mon Sep 17 00:00:00 2001 From: tbekos Date: Thu, 18 Apr 2013 12:09:03 +0300 Subject: [PATCH] feat(pagination): option for different mode when maxSize * Allow user to specify if current page is rotated, moving the left/right limit, or page is moving between page groups. --- src/pagination/docs/demo.html | 18 ++++-- src/pagination/docs/demo.js | 3 + src/pagination/docs/readme.md | 3 +- src/pagination/pagination.js | 46 +++++++++++---- src/pagination/test/pagination.spec.js | 79 ++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 17 deletions(-) diff --git a/src/pagination/docs/demo.html b/src/pagination/docs/demo.html index 92e1dfc07c..dddba3b056 100644 --- a/src/pagination/docs/demo.html +++ b/src/pagination/docs/demo.html @@ -1,9 +1,17 @@ -
+
+

Default

+ - - - + + + The selected page no: {{currentPage}} -
\ No newline at end of file + +
+ +

Limit the maximimum visible page-buttons

+ + +
diff --git a/src/pagination/docs/demo.js b/src/pagination/docs/demo.js index e80756526f..7ae5ef6769 100644 --- a/src/pagination/docs/demo.js +++ b/src/pagination/docs/demo.js @@ -6,4 +6,7 @@ var PaginationDemoCtrl = function ($scope) { $scope.setPage = function (pageNo) { $scope.currentPage = pageNo; }; + + $scope.bigNoOfPages = 18; + $scope.bigCurrentPage = 1; }; diff --git a/src/pagination/docs/readme.md b/src/pagination/docs/readme.md index b4fab8b7f0..ae72b495b0 100644 --- a/src/pagination/docs/readme.md +++ b/src/pagination/docs/readme.md @@ -1,5 +1,6 @@ + A lightweight pagination directive that is focused on ... providing pagination! It will take care of visualising a pagination bar. Additionally it will make sure that the state (enabled / disabled) of the Previous / Next and First / Last buttons (if exist) is maintained correctly. -It also provides optional attribute max-size to limit the size of pagination bar. \ No newline at end of file +It also provides optional attribute max-size to limit the size of pagination bar & rotate attribute whether to keep current page in the middle of the visible ones. diff --git a/src/pagination/pagination.js b/src/pagination/pagination.js index d042958282..29aa6c4b31 100644 --- a/src/pagination/pagination.js +++ b/src/pagination/pagination.js @@ -6,7 +6,8 @@ angular.module('ui.bootstrap.pagination', []) firstText: 'First', previousText: 'Previous', nextText: 'Next', - lastText: 'Last' + lastText: 'Last', + rotate: true }) .directive('pagination', ['paginationConfig', function(paginationConfig) { @@ -29,6 +30,7 @@ angular.module('ui.bootstrap.pagination', []) var previousText = angular.isDefined(attrs.previousText) ? attrs.previousText : paginationConfig.previousText; var nextText = angular.isDefined(attrs.nextText) ? attrs.nextText : paginationConfig.nextText; var lastText = angular.isDefined(attrs.lastText) ? attrs.lastText : paginationConfig.lastText; + var rotate = angular.isDefined(attrs.rotate) ? scope.$eval(attrs.rotate) : paginationConfig.rotate; // Create page object used in template function makePage(number, text, isActive, isDisabled) { @@ -45,16 +47,26 @@ angular.module('ui.bootstrap.pagination', []) // Default page limits var startPage = 1, endPage = scope.numPages; + var isMaxSized = ( angular.isDefined(scope.maxSize) && scope.maxSize < scope.numPages ); // recompute if maxSize - if ( scope.maxSize && scope.maxSize < scope.numPages ) { - startPage = Math.max(scope.currentPage - Math.floor(scope.maxSize/2), 1); - endPage = startPage + scope.maxSize - 1; - - // Adjust if limit is exceeded - if (endPage > scope.numPages) { - endPage = scope.numPages; - startPage = endPage - scope.maxSize + 1; + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(scope.currentPage - Math.floor(scope.maxSize/2), 1); + endPage = startPage + scope.maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > scope.numPages) { + endPage = scope.numPages; + startPage = endPage - scope.maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(scope.currentPage / scope.maxSize) - 1) * scope.maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + scope.maxSize - 1, scope.numPages); } } @@ -64,6 +76,19 @@ angular.module('ui.bootstrap.pagination', []) scope.pages.push(page); } + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false, false); + scope.pages.unshift(previousPageSet); + } + + if ( endPage < scope.numPages ) { + var nextPageSet = makePage(endPage + 1, '...', false, false); + scope.pages.push(nextPageSet); + } + } + // Add previous & next links if (directionLinks) { var previousPage = makePage(scope.currentPage - 1, previousText, false, scope.noPrevious()); @@ -82,7 +107,6 @@ angular.module('ui.bootstrap.pagination', []) scope.pages.push(lastPage); } - if ( scope.currentPage > scope.numPages ) { scope.selectPage(scope.numPages); } @@ -105,4 +129,4 @@ angular.module('ui.bootstrap.pagination', []) }; } }; -}]); \ No newline at end of file +}]); diff --git a/src/pagination/test/pagination.spec.js b/src/pagination/test/pagination.spec.js index 1a49709ce4..80966a9505 100644 --- a/src/pagination/test/pagination.spec.js +++ b/src/pagination/test/pagination.spec.js @@ -190,6 +190,85 @@ describe('pagination directive with max size option', function () { expect($rootScope.maxSize).toBe(15); }); + it('should not display page numbers, if max-size is zero', function() { + $rootScope.maxSize = 0; + $rootScope.$digest(); + expect(element.find('li').length).toBe(2); + expect(element.find('li').eq(0).text()).toBe('Previous'); + expect(element.find('li').eq(-1).text()).toBe('Next'); + }); + +}); + +describe('pagination directive with max size option & no rotate', function () { + var $rootScope, element; + beforeEach(module('ui.bootstrap.pagination')); + beforeEach(module('template/pagination/pagination.html')); + beforeEach(inject(function(_$compile_, _$rootScope_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $rootScope.numPages = 12; + $rootScope.currentPage = 7; + $rootScope.maxSize = 5; + element = $compile('')($rootScope); + $rootScope.$digest(); + })); + + it('contains one ul and maxsize + 4 elements', function() { + expect(element.find('ul').length).toBe(1); + expect(element.find('li').length).toBe($rootScope.maxSize + 4); + expect(element.find('li').eq(0).text()).toBe('Previous'); + expect(element.find('li').eq(1).text()).toBe('...'); + expect(element.find('li').eq(2).text()).toBe('6'); + expect(element.find('li').eq(-3).text()).toBe('10'); + expect(element.find('li').eq(-2).text()).toBe('...'); + expect(element.find('li').eq(-1).text()).toBe('Next'); + }); + + it('shows only the next ellipsis element on first page set', function() { + $rootScope.currentPage = 3; + $rootScope.$digest(); + expect(element.find('li').eq(1).text()).toBe('1'); + expect(element.find('li').eq(-3).text()).toBe('5'); + expect(element.find('li').eq(-2).text()).toBe('...'); + }); + + it('shows only the previous ellipsis element on last page set', function() { + $rootScope.currentPage = 12; + $rootScope.$digest(); + expect(element.find('li').length).toBe(5); + expect(element.find('li').eq(1).text()).toBe('...'); + expect(element.find('li').eq(2).text()).toBe('11'); + expect(element.find('li').eq(-2).text()).toBe('12'); + }); + + it('moves to the previous set when first ellipsis is clicked', function() { + var prev = element.find('li').eq(1).find('a').eq(0); + expect(prev.text()).toBe('...'); + + prev.click(); + expect($rootScope.currentPage).toBe(5); + var currentPageItem = element.find('li').eq(-3); + expect(currentPageItem.hasClass('active')).toBe(true); + }); + + it('moves to the next set when last ellipsis is clicked', function() { + var next = element.find('li').eq(-2).find('a').eq(0); + expect(next.text()).toBe('...'); + + next.click(); + expect($rootScope.currentPage).toBe(11); + var currentPageItem = element.find('li').eq(2); + expect(currentPageItem.hasClass('active')).toBe(true); + }); + + it('should not display page numbers, if max-size is zero', function() { + $rootScope.maxSize = 0; + $rootScope.$digest(); + expect(element.find('li').length).toBe(2); + expect(element.find('li').eq(0).text()).toBe('Previous'); + expect(element.find('li').eq(-1).text()).toBe('Next'); + }); }); describe('pagination directive with added first & last links', function () {