diff --git a/src/pagination/pagination.js b/src/pagination/pagination.js index b66bab5aba..25cad7f524 100644 --- a/src/pagination/pagination.js +++ b/src/pagination/pagination.js @@ -1,19 +1,33 @@ angular.module('ui.bootstrap.pagination', []) -.directive('pagination', function() { +.constant('paginationConfig', { + boundary: false, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last' +}) + +.directive('pagination', ['paginationConfig', function(paginationConfig) { return { restrict: 'EA', scope: { numPages: '=', currentPage: '=', maxSize: '=', - onSelectPage: '&', - nextText: '@', - previousText: '@' + onSelectPage: '&' }, templateUrl: 'template/pagination/pagination.html', replace: true, - link: function(scope) { + link: function(scope, element, attrs) { + + // Set configuration parameters in scope + scope.boundary = angular.isDefined(attrs.boundary) ? scope.$eval(attrs.boundary) : paginationConfig.boundary; + scope.firstText = angular.isDefined(attrs.firstText) ? attrs.firstText : paginationConfig.firstText; + scope.previousText = angular.isDefined(attrs.previousText) ? attrs.previousText : paginationConfig.previousText; + scope.nextText = angular.isDefined(attrs.nextText) ? attrs.nextText : paginationConfig.nextText; + scope.lastText = angular.isDefined(attrs.lastText) ? attrs.lastText : paginationConfig.lastText; + scope.$watch('numPages + currentPage + maxSize', function() { scope.pages = []; @@ -63,6 +77,13 @@ angular.module('ui.bootstrap.pagination', []) scope.selectPage(scope.currentPage+1); } }; + + scope.selectFirst = function() { + scope.selectPage(1); + }; + scope.selectLast = function() { + scope.selectPage(scope.numPages); + }; } }; -}); \ No newline at end of file +}]); \ No newline at end of file diff --git a/src/pagination/test/pagination.spec.js b/src/pagination/test/pagination.spec.js index 356168432a..98b37998f0 100644 --- a/src/pagination/test/pagination.spec.js +++ b/src/pagination/test/pagination.spec.js @@ -1,5 +1,5 @@ describe('pagination directive', function () { - var $rootScope, element; + var $rootScope, element, position; beforeEach(module('ui.bootstrap.pagination')); beforeEach(module('template/pagination/pagination.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { @@ -9,28 +9,44 @@ describe('pagination directive', function () { $rootScope.currentPage = 3; element = $compile('')($rootScope); $rootScope.$digest(); + position = { + first: 0, + previous: 1, + next: -2, + last: -1 + }; })); it('has a "pagination" css class', function() { expect(element.hasClass('pagination')).toBe(true); }); - it('contains one ul and num-pages + 2 li elements', function() { + it('contains one ul and num-pages + 4 li elements', function() { expect(element.find('ul').length).toBe(1); - expect(element.find('li').length).toBe(7); - expect(element.find('li').eq(0).text()).toBe('Previous'); - expect(element.find('li').eq(-1).text()).toBe('Next'); + expect(element.find('li').length).toBe(9); + expect(element.find('li').eq(position.previous).text()).toBe('Previous'); + expect(element.find('li').eq(position.next).text()).toBe('Next'); + }); + + it('has first and last li hidden', function() { + var firstLiEl = element.find('li').eq(position.first); + var lastLiEl = element.find('li').eq(position.last); + + expect(firstLiEl.text()).toBe('First'); + expect(firstLiEl.css('display')).toBe('none'); + expect(lastLiEl.text()).toBe('Last'); + expect(lastLiEl.css('display')).toBe('none'); }); it('has the number of the page as text in each page item', function() { var lis = element.find('li'); - for(var i=1; i<=$rootScope.numPages;i++) { - expect(lis.eq(i).text()).toEqual(''+i); + for(var i=position.previous + 1; i<=$rootScope.numPages;i++) { + expect(lis.eq(i).text()).toEqual(''+(i-1)); } }); it('sets the current-page to be active', function() { - var currentPageItem = element.find('li').eq($rootScope.currentPage); + var currentPageItem = element.find('li').eq($rootScope.currentPage + 1); expect(currentPageItem.hasClass('active')).toBe(true); }); @@ -49,28 +65,28 @@ describe('pagination directive', function () { }); it('changes currentPage if a page link is clicked', function() { - var page2 = element.find('li').eq(2).find('a'); + var page2 = element.find('li').eq(3).find('a'); page2.click(); $rootScope.$digest(); expect($rootScope.currentPage).toBe(2); }); it('changes currentPage if the "previous" link is clicked', function() { - var previous = element.find('li').eq(0).find('a').eq(0); + var previous = element.find('li').eq(position.previous).find('a').eq(0); previous.click(); $rootScope.$digest(); expect($rootScope.currentPage).toBe(2); }); it('changes currentPage if the "next" link is clicked', function() { - var next = element.find('li').eq(-1).find('a').eq(0); + var next = element.find('li').eq(position.next).find('a').eq(0); next.click(); $rootScope.$digest(); expect($rootScope.currentPage).toBe(4); }); it('does not change the current page on "previous" click if already at first page', function() { - var previous = element.find('li').eq(0).find('a').eq(0); + var previous = element.find('li').eq(position.previous).find('a').eq(0); $rootScope.currentPage = 1; $rootScope.$digest(); previous.click(); @@ -91,7 +107,7 @@ describe('pagination directive', function () { $rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler'); element = $compile('')($rootScope); $rootScope.$digest(); - var page2 = element.find('li').eq(2).find('a').eq(0); + var page2 = element.find('li').eq(3).find('a').eq(0); page2.click(); $rootScope.$digest(); expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2); @@ -100,9 +116,9 @@ describe('pagination directive', function () { it('changes the number of items when numPages changes', function() { $rootScope.numPages = 8; $rootScope.$digest(); - expect(element.find('li').length).toBe(10); - expect(element.find('li').eq(0).text()).toBe('Previous'); - expect(element.find('li').eq(-1).text()).toBe('Next'); + expect(element.find('li').length).toBe(12); + expect(element.find('li').eq(position.previous).text()).toBe('Previous'); + expect(element.find('li').eq(position.next).text()).toBe('Next'); }); it('sets the current page to the last page if the numPages is changed to less than the current page', function() { @@ -111,14 +127,14 @@ describe('pagination directive', function () { $rootScope.$digest(); $rootScope.numPages = 2; $rootScope.$digest(); - expect(element.find('li').length).toBe(4); + expect(element.find('li').length).toBe(6); expect($rootScope.currentPage).toBe(2); expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2); }); }); describe('pagination directive with max size option', function () { - var $rootScope, element; + var $rootScope, element, position; beforeEach(module('ui.bootstrap.pagination')); beforeEach(module('template/pagination/pagination.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { @@ -129,34 +145,40 @@ describe('pagination directive with max size option', function () { $rootScope.maxSize = 5; element = $compile('')($rootScope); $rootScope.$digest(); + position = { + first: 0, + previous: 1, + next: -2, + last: -1 + }; })); - it('contains one ul and maxsize + 2 li elements', function() { + it('contains one ul and maxsize + 4 li elements', function() { expect(element.find('ul').length).toBe(1); - expect(element.find('li').length).toBe($rootScope.maxSize + 2); - expect(element.find('li').eq(0).text()).toBe('Previous'); - expect(element.find('li').eq(-1).text()).toBe('Next'); + expect(element.find('li').length).toBe($rootScope.maxSize + 4); + expect(element.find('li').eq(position.previous).text()).toBe('Previous'); + expect(element.find('li').eq(position.next).text()).toBe('Next'); }); it('shows the page number even if it can\'t be shown in the middle', function() { $rootScope.currentPage = 1; $rootScope.$digest(); - var currentPageItem = element.find('li').eq(1); + var currentPageItem = element.find('li').eq(2); expect(currentPageItem.hasClass('active')).toBe(true); $rootScope.currentPage = 10; $rootScope.$digest(); - currentPageItem = element.find('li').eq(-2); + currentPageItem = element.find('li').eq(-3); expect(currentPageItem.hasClass('active')).toBe(true); }); it('shows the page number in middle after the next link is clicked', function() { $rootScope.currentPage = 6; $rootScope.$digest(); - var next = element.find('li').eq(-1).find('a').eq(0); + var next = element.find('li').eq(position.next).find('a').eq(0); next.click(); expect($rootScope.currentPage).toBe(7); - var currentPageItem = element.find('li').eq(3); + var currentPageItem = element.find('li').eq(4); expect(currentPageItem.hasClass('active')).toBe(true); expect(parseInt(currentPageItem.text(), 10)).toBe($rootScope.currentPage); }); @@ -164,10 +186,10 @@ describe('pagination directive with max size option', function () { it('shows the page number in middle after the prev link is clicked', function() { $rootScope.currentPage = 7; $rootScope.$digest(); - var prev = element.find('li').eq(0).find('a').eq(0); + var prev = element.find('li').eq(position.previous).find('a').eq(0); prev.click(); expect($rootScope.currentPage).toBe(6); - var currentPageItem = element.find('li').eq(3); + var currentPageItem = element.find('li').eq(4); expect(currentPageItem.hasClass('active')).toBe(true); expect(parseInt(currentPageItem.text(), 10)).toBe($rootScope.currentPage); }); @@ -175,13 +197,13 @@ describe('pagination directive with max size option', function () { it('changes pagination bar size when max-size value changed', function() { $rootScope.maxSize = 7; $rootScope.$digest(); - expect(element.find('li').length).toBe(9); + expect(element.find('li').length).toBe(11); }); it('sets the pagination bar size to num-pages, if max-size is greater than num-pages ', function() { $rootScope.maxSize = 15; $rootScope.$digest(); - expect(element.find('li').length).toBe(12); + expect(element.find('li').length).toBe(14); }); it('should not change value of max-size expression, if max-size is greater than num-pages ', function() { @@ -192,8 +214,86 @@ describe('pagination directive with max size option', function () { }); -describe('pagination custom', function () { - var $rootScope, element; +describe('pagination bypass default configuration', function () { + var $rootScope, element, position; + beforeEach(module('ui.bootstrap.pagination')); + beforeEach(module('template/pagination/pagination.html')); + beforeEach(inject(function(_$compile_, _$rootScope_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $rootScope.numPages = 5; + $rootScope.currentPage = 3; + element = $compile('')($rootScope); + $rootScope.$digest(); + position = { + first: 0, + previous: 1, + next: -2, + last: -1 + }; + })); + + it('should change paging text from attributes', function () { + expect(element.find('li').eq(position.first).text()).toBe('<<'); + expect(element.find('li').eq(position.previous).text()).toBe('<'); + expect(element.find('li').eq(position.next).text()).toBe('>'); + expect(element.find('li').eq(position.last).text()).toBe('>>'); + }); + + it('should display first & last button', function () { + expect(element.find('li').eq(position.first).css('display')).not.toBe('none'); + expect(element.find('li').eq(position.last).css('display')).not.toBe('none'); + }); + +}); + + +describe('setting paginationConfig', function() { + var $rootScope, element, position; + var originalConfig = {}; + beforeEach(module('ui.bootstrap.pagination')); + beforeEach(module('template/pagination/pagination.html')); + beforeEach(inject(function(_$compile_, _$rootScope_, paginationConfig) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $rootScope.numPages = 5; + $rootScope.currentPage = 3; + angular.extend(originalConfig, paginationConfig); + paginationConfig.boundary = true; + paginationConfig.firstText = 'FI'; + paginationConfig.previousText = 'PR'; + paginationConfig.nextText = 'NE'; + paginationConfig.lastText = 'LA'; + element = $compile('')($rootScope); + $rootScope.$digest(); + position = { + first: 0, + previous: 1, + next: -2, + last: -1 + }; + })); + afterEach(inject(function(paginationConfig) { + // return it to the original state + angular.extend(paginationConfig, originalConfig); + })); + + it('should change paging text', function () { + expect(element.find('li').eq(position.first).text()).toBe('FI'); + expect(element.find('li').eq(position.previous).text()).toBe('PR'); + expect(element.find('li').eq(position.next).text()).toBe('NE'); + expect(element.find('li').eq(position.last).text()).toBe('LA'); + }); + + it('should display first & last button', function () { + expect(element.find('li').eq(position.first).css('display')).not.toBe('none'); + expect(element.find('li').eq(position.last).css('display')).not.toBe('none'); + }); +}); + + +describe('pagination with first & last elements', function () { + var $rootScope, element, position; beforeEach(module('ui.bootstrap.pagination')); beforeEach(module('template/pagination/pagination.html')); beforeEach(inject(function(_$compile_, _$rootScope_) { @@ -201,13 +301,90 @@ describe('pagination custom', function () { $rootScope = _$rootScope_; $rootScope.numPages = 5; $rootScope.currentPage = 3; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); + position = { + first: 0, + previous: 1, + next: -2, + last: -1 + }; })); - it('should change paging text from attribute', function () { - expect(element.find('li').eq(0).text()).toBe('<<'); - expect(element.find('li').eq(-1).text()).toBe('>>'); + + it('contains one ul and num-pages + 4 li elements', function() { + expect(element.find('ul').length).toBe(1); + expect(element.find('li').length).toBe(9); + expect(element.find('li').eq(position.previous).text()).toBe('Previous'); + expect(element.find('li').eq(position.next).text()).toBe('Next'); + expect(element.find('li').eq(position.first).text()).toBe('First'); + expect(element.find('li').eq(position.last).text()).toBe('Last'); + }); + + it('has first and last li visible', function() { + var firstLiEl = element.find('li').eq(position.first); + var lastLiEl = element.find('li').eq(position.last); + + expect(firstLiEl.text()).toBe('First'); + expect(firstLiEl.css('display')).not.toBe('none'); + expect(lastLiEl.text()).toBe('Last'); + expect(lastLiEl.css('display')).not.toBe('none'); + }); + + + it('disables the "first" link if current-page is 1', function() { + $rootScope.currentPage = 1; + $rootScope.$digest(); + var firstPageItem = element.find('li').eq(position.first); + expect(firstPageItem.hasClass('disabled')).toBe(true); + }); + + it('disables the "last" link if current-page is num-pages', function() { + $rootScope.currentPage = 5; + $rootScope.$digest(); + var lastPageItem = element.find('li').eq(position.last); + expect(lastPageItem.hasClass('disabled')).toBe(true); + }); + + + it('changes currentPage if the "first" link is clicked', function() { + var first = element.find('li').eq(position.first).find('a').eq(0); + first.click(); + $rootScope.$digest(); + expect($rootScope.currentPage).toBe(1); + }); + + it('changes currentPage if the "last" link is clicked', function() { + var last = element.find('li').eq(position.last).find('a').eq(0); + last.click(); + $rootScope.$digest(); + expect($rootScope.currentPage).toBe($rootScope.numPages); + }); + + it('does not change the current page on "first" click if already at first page', function() { + var first = element.find('li').eq(position.first).find('a').eq(0); + $rootScope.currentPage = 1; + $rootScope.$digest(); + first.click(); + $rootScope.$digest(); + expect($rootScope.currentPage).toBe(1); + }); + + it('does not change the current page on "last" click if already at last page', function() { + var last = element.find('li').eq(position.last).find('a').eq(0); + $rootScope.currentPage = $rootScope.numPages; + $rootScope.$digest(); + last.click(); + $rootScope.$digest(); + expect($rootScope.currentPage).toBe($rootScope.numPages); + }); + + it('changes text from attributes', function() { + element = $compile('')($rootScope); + $rootScope.$digest(); + + expect(element.find('li').eq(position.first).text()).toBe('<<<'); + expect(element.find('li').eq(position.last).text()).toBe('>>>'); }); }); diff --git a/template/pagination/pagination.html b/template/pagination/pagination.html index 4c0d40baac..8aba3fe10c 100644 --- a/template/pagination/pagination.html +++ b/template/pagination/pagination.html @@ -1,6 +1,8 @@