diff --git a/src/pagination/docs/demo.html b/src/pagination/docs/demo.html
index 6eb217081c..13c4d83527 100644
--- a/src/pagination/docs/demo.html
+++ b/src/pagination/docs/demo.html
@@ -10,7 +10,10 @@
Default
The selected page no: {{currentPage}}
+ Pager
+
+
Limit the maximimum visible page-buttons
diff --git a/src/pagination/docs/readme.md b/src/pagination/docs/readme.md
index 4a3d62964f..8394e5bb8d 100644
--- a/src/pagination/docs/readme.md
+++ b/src/pagination/docs/readme.md
@@ -1,7 +1,7 @@
A lightweight pagination directive that is focused on ... providing pagination & will take care of visualising a pagination bar and enable / disable buttons correctly!
-### Settings ###
+### Pagination Settings ###
Settings can be provided as attributes in the `` or globally configured through the `paginationConfig`.
@@ -49,3 +49,19 @@ Settings can be provided as attributes in the `` or globally configu
_(Default: 'Last')_ :
Text for Last button.
+### Pager Settings ###
+
+Settings can be provided as attributes in the `` or globally configured through the `pagerConfig`.
+For `num-pages`, `current-page` and `on-select-page (page)` see pagination settings. Other settings are:
+
+ * `align`
+ _(Default: true)_ :
+ Whether to align each link to the sides.
+
+ * `previous-text`
+ _(Default: '« Previous')_ :
+ Text for Previous button.
+
+ * `next-text`
+ _(Default: 'Next »')_ :
+ Text for Next button.
diff --git a/src/pagination/pagination.js b/src/pagination/pagination.js
index 6abc75aba0..69aec65c52 100644
--- a/src/pagination/pagination.js
+++ b/src/pagination/pagination.js
@@ -1,5 +1,26 @@
angular.module('ui.bootstrap.pagination', [])
+.controller('PaginationController', ['$scope', function (scope) {
+
+ scope.noPrevious = function() {
+ return scope.currentPage === 1;
+ };
+ scope.noNext = function() {
+ return scope.currentPage === scope.numPages;
+ };
+
+ scope.isActive = function(page) {
+ return scope.currentPage === page;
+ };
+
+ scope.selectPage = function(page) {
+ if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {
+ scope.currentPage = page;
+ scope.onSelectPage({ page: page });
+ }
+ };
+}])
+
.constant('paginationConfig', {
boundaryLinks: false,
directionLinks: true,
@@ -19,6 +40,7 @@ angular.module('ui.bootstrap.pagination', [])
maxSize: '=',
onSelectPage: '&'
},
+ controller: 'PaginationController',
templateUrl: 'template/pagination/pagination.html',
replace: true,
link: function(scope, element, attrs) {
@@ -111,22 +133,59 @@ angular.module('ui.bootstrap.pagination', [])
scope.selectPage(scope.numPages);
}
});
- scope.noPrevious = function() {
- return scope.currentPage === 1;
- };
- scope.noNext = function() {
- return scope.currentPage === scope.numPages;
- };
- scope.isActive = function(page) {
- return scope.currentPage === page;
- };
-
- scope.selectPage = function(page) {
- if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {
- scope.currentPage = page;
- scope.onSelectPage({ page: page });
+ }
+ };
+}])
+
+.constant('pagerConfig', {
+ previousText: '« Previous',
+ nextText: 'Next »',
+ align: true
+})
+
+.directive('pager', ['pagerConfig', function(config) {
+ return {
+ restrict: 'EA',
+ scope: {
+ numPages: '=',
+ currentPage: '=',
+ onSelectPage: '&'
+ },
+ controller: 'PaginationController',
+ templateUrl: 'template/pagination/pager.html',
+ replace: true,
+ link: function(scope, element, attrs, paginationCtrl) {
+
+ // Setup configuration parameters
+ var previousText = angular.isDefined(attrs.previousText) ? scope.$parent.$eval(attrs.previousText) : config.previousText;
+ var nextText = angular.isDefined(attrs.nextText) ? scope.$parent.$eval(attrs.nextText) : config.nextText;
+ var align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : config.align;
+
+ // Create page object used in template
+ function makePage(number, text, isDisabled, isPrevious, isNext) {
+ return {
+ number: number,
+ text: text,
+ disabled: isDisabled,
+ previous: ( align && isPrevious ),
+ next: ( align && isNext )
+ };
+ }
+
+ scope.$watch('numPages + currentPage', function() {
+ scope.pages = [];
+
+ // Add previous & next links
+ var previousPage = makePage(scope.currentPage - 1, previousText, scope.noPrevious(), true, false);
+ scope.pages.unshift(previousPage);
+
+ var nextPage = makePage(scope.currentPage + 1, nextText, scope.noNext(), false, true);
+ scope.pages.push(nextPage);
+
+ if ( scope.currentPage > scope.numPages ) {
+ scope.selectPage(scope.numPages);
}
- };
+ });
}
};
}]);
diff --git a/src/pagination/test/pager.spec.js b/src/pagination/test/pager.spec.js
new file mode 100644
index 0000000000..1dbec62ba4
--- /dev/null
+++ b/src/pagination/test/pager.spec.js
@@ -0,0 +1,171 @@
+describe('pager directive with default configuration', function () {
+ var $rootScope, element;
+ beforeEach(module('ui.bootstrap.pagination'));
+ beforeEach(module('template/pagination/pager.html'));
+ beforeEach(inject(function(_$compile_, _$rootScope_) {
+ $compile = _$compile_;
+ $rootScope = _$rootScope_;
+ $rootScope.numPages = 5;
+ $rootScope.currentPage = 3;
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+ }));
+
+ it('has a "pager" css class', function() {
+ expect(element.hasClass('pager')).toBe(true);
+ });
+
+ it('contains 2 li elements', function() {
+ 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 »');
+ });
+
+ it('aligns previous & next page', function() {
+ expect(element.find('li').eq(0).hasClass('previous')).toBe(true);
+ expect(element.find('li').eq(0).hasClass('next')).toBe(false);
+
+ expect(element.find('li').eq(-1).hasClass('previous')).toBe(false);
+ expect(element.find('li').eq(-1).hasClass('next')).toBe(true);
+ });
+
+ it('disables the "previous" link if current-page is 1', function() {
+ $rootScope.currentPage = 1;
+ $rootScope.$digest();
+ expect(element.find('li').eq(0).hasClass('disabled')).toBe(true);
+ });
+
+ it('disables the "next" link if current-page is num-pages', function() {
+ $rootScope.currentPage = 5;
+ $rootScope.$digest();
+ expect(element.find('li').eq(-1).hasClass('disabled')).toBe(true);
+ });
+
+ it('changes currentPage if the "previous" link is clicked', function() {
+ var previous = element.find('li').eq(0).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);
+ 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);
+ $rootScope.currentPage = 1;
+ $rootScope.$digest();
+ previous.click();
+ $rootScope.$digest();
+ expect($rootScope.currentPage).toBe(1);
+ });
+
+ it('does not change the current page on "next" click if already at last page', function() {
+ var next = element.find('li').eq(-1).find('a').eq(0);
+ $rootScope.currentPage = 5;
+ $rootScope.$digest();
+ next.click();
+ $rootScope.$digest();
+ expect($rootScope.currentPage).toBe(5);
+ });
+
+ it('executes the onSelectPage expression when the current page changes', function() {
+ $rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+ var next = element.find('li').eq(-1).find('a').eq(0);
+ next.click();
+ $rootScope.$digest();
+ expect($rootScope.selectPageHandler).toHaveBeenCalledWith(4);
+ });
+
+ it('does not changes the number of items when numPages changes', function() {
+ $rootScope.numPages = 8;
+ $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 »');
+ });
+
+ it('sets the current page to the last page if the numPages is changed to less than the current page', function() {
+ $rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+ $rootScope.numPages = 2;
+ $rootScope.$digest();
+ expect(element.find('li').length).toBe(2);
+ expect($rootScope.currentPage).toBe(2);
+ expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2);
+ });
+});
+
+describe('setting pagerConfig', function() {
+ var $rootScope, element;
+ var originalConfig = {};
+ beforeEach(module('ui.bootstrap.pagination'));
+ beforeEach(module('template/pagination/pager.html'));
+ beforeEach(inject(function(_$compile_, _$rootScope_, pagerConfig) {
+ $compile = _$compile_;
+ $rootScope = _$rootScope_;
+ $rootScope.numPages = 5;
+ $rootScope.currentPage = 3;
+ angular.extend(originalConfig, pagerConfig);
+ pagerConfig.previousText = 'PR';
+ pagerConfig.nextText = 'NE';
+ pagerConfig.align = false;
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+ }));
+ afterEach(inject(function(pagerConfig) {
+ // return it to the original state
+ angular.extend(pagerConfig, originalConfig);
+ }));
+
+ it('contains 2 li elements', function() {
+ expect(element.find('li').length).toBe(2);
+ });
+
+ it('should change paging text', function () {
+ expect(element.find('li').eq(0).text()).toBe('PR');
+ expect(element.find('li').eq(-1).text()).toBe('NE');
+ });
+
+ it('should not align previous & next page link', function () {
+ expect(element.find('li').eq(0).hasClass('previous')).toBe(false);
+ expect(element.find('li').eq(-1).hasClass('next')).toBe(false);
+ });
+
+});
+
+describe('pagination bypass configuration from attributes', function () {
+ var $rootScope, element;
+ beforeEach(module('ui.bootstrap.pagination'));
+ beforeEach(module('template/pagination/pager.html'));
+ beforeEach(inject(function(_$compile_, _$rootScope_) {
+ $compile = _$compile_;
+ $rootScope = _$rootScope_;
+ $rootScope.numPages = 5;
+ $rootScope.currentPage = 3;
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+ }));
+
+ it('contains 2 li elements', function() {
+ expect(element.find('li').length).toBe(2);
+ });
+
+ it('should change paging text from attributes', function () {
+ expect(element.find('li').eq(0).text()).toBe('<');
+ expect(element.find('li').eq(-1).text()).toBe('>');
+ });
+
+ it('should not align previous & next page link', function () {
+ expect(element.find('li').eq(0).hasClass('previous')).toBe(false);
+ expect(element.find('li').eq(-1).hasClass('next')).toBe(false);
+ });
+
+});
\ No newline at end of file
diff --git a/template/pagination/pager.html b/template/pagination/pager.html
new file mode 100644
index 0000000000..74b77f2d8b
--- /dev/null
+++ b/template/pagination/pager.html
@@ -0,0 +1,5 @@
+