Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit d952647

Browse files
bekospkozlowski-opensource
authored andcommitted
feat(pagination): add pager directive
1 parent 88c94ee commit d952647

File tree

5 files changed

+270
-16
lines changed

5 files changed

+270
-16
lines changed

src/pagination/docs/demo.html

+3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ <h4>Default</h4>
1010
The selected page no: {{currentPage}}
1111

1212
<hr />
13+
<h4>Pager</h4>
14+
<pager num-pages="noOfPages" current-page="currentPage"></pager>
1315

16+
<hr />
1417
<h4>Limit the maximimum visible page-buttons</h4>
1518
<pagination num-pages="bigNoOfPages" current-page="bigCurrentPage" max-size="maxSize" class="pagination-mini" boundary-links="true"></pagination>
1619
<pagination rotate="false" num-pages="bigNoOfPages" current-page="bigCurrentPage" max-size="maxSize" class="pagination-mini" boundary-links="true"></pagination>

src/pagination/docs/readme.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
A lightweight pagination directive that is focused on ... providing pagination & will take care of visualising a pagination bar and enable / disable buttons correctly!
33

4-
### Settings ###
4+
### Pagination Settings ###
55

66
Settings can be provided as attributes in the `<pagination>` or globally configured through the `paginationConfig`.
77

@@ -49,3 +49,19 @@ Settings can be provided as attributes in the `<pagination>` or globally configu
4949
_(Default: 'Last')_ :
5050
Text for Last button.
5151

52+
### Pager Settings ###
53+
54+
Settings can be provided as attributes in the `<pager>` or globally configured through the `pagerConfig`.
55+
For `num-pages`, `current-page` and `on-select-page (page)` see pagination settings. Other settings are:
56+
57+
* `align`
58+
_(Default: true)_ :
59+
Whether to align each link to the sides.
60+
61+
* `previous-text`
62+
_(Default: '« Previous')_ :
63+
Text for Previous button.
64+
65+
* `next-text`
66+
_(Default: 'Next »')_ :
67+
Text for Next button.

src/pagination/pagination.js

+74-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
angular.module('ui.bootstrap.pagination', [])
22

3+
.controller('PaginationController', ['$scope', function (scope) {
4+
5+
scope.noPrevious = function() {
6+
return scope.currentPage === 1;
7+
};
8+
scope.noNext = function() {
9+
return scope.currentPage === scope.numPages;
10+
};
11+
12+
scope.isActive = function(page) {
13+
return scope.currentPage === page;
14+
};
15+
16+
scope.selectPage = function(page) {
17+
if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {
18+
scope.currentPage = page;
19+
scope.onSelectPage({ page: page });
20+
}
21+
};
22+
}])
23+
324
.constant('paginationConfig', {
425
boundaryLinks: false,
526
directionLinks: true,
@@ -19,6 +40,7 @@ angular.module('ui.bootstrap.pagination', [])
1940
maxSize: '=',
2041
onSelectPage: '&'
2142
},
43+
controller: 'PaginationController',
2244
templateUrl: 'template/pagination/pagination.html',
2345
replace: true,
2446
link: function(scope, element, attrs) {
@@ -111,22 +133,59 @@ angular.module('ui.bootstrap.pagination', [])
111133
scope.selectPage(scope.numPages);
112134
}
113135
});
114-
scope.noPrevious = function() {
115-
return scope.currentPage === 1;
116-
};
117-
scope.noNext = function() {
118-
return scope.currentPage === scope.numPages;
119-
};
120-
scope.isActive = function(page) {
121-
return scope.currentPage === page;
122-
};
123-
124-
scope.selectPage = function(page) {
125-
if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {
126-
scope.currentPage = page;
127-
scope.onSelectPage({ page: page });
136+
}
137+
};
138+
}])
139+
140+
.constant('pagerConfig', {
141+
previousText: '« Previous',
142+
nextText: 'Next »',
143+
align: true
144+
})
145+
146+
.directive('pager', ['pagerConfig', function(config) {
147+
return {
148+
restrict: 'EA',
149+
scope: {
150+
numPages: '=',
151+
currentPage: '=',
152+
onSelectPage: '&'
153+
},
154+
controller: 'PaginationController',
155+
templateUrl: 'template/pagination/pager.html',
156+
replace: true,
157+
link: function(scope, element, attrs, paginationCtrl) {
158+
159+
// Setup configuration parameters
160+
var previousText = angular.isDefined(attrs.previousText) ? scope.$parent.$eval(attrs.previousText) : config.previousText;
161+
var nextText = angular.isDefined(attrs.nextText) ? scope.$parent.$eval(attrs.nextText) : config.nextText;
162+
var align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : config.align;
163+
164+
// Create page object used in template
165+
function makePage(number, text, isDisabled, isPrevious, isNext) {
166+
return {
167+
number: number,
168+
text: text,
169+
disabled: isDisabled,
170+
previous: ( align && isPrevious ),
171+
next: ( align && isNext )
172+
};
173+
}
174+
175+
scope.$watch('numPages + currentPage', function() {
176+
scope.pages = [];
177+
178+
// Add previous & next links
179+
var previousPage = makePage(scope.currentPage - 1, previousText, scope.noPrevious(), true, false);
180+
scope.pages.unshift(previousPage);
181+
182+
var nextPage = makePage(scope.currentPage + 1, nextText, scope.noNext(), false, true);
183+
scope.pages.push(nextPage);
184+
185+
if ( scope.currentPage > scope.numPages ) {
186+
scope.selectPage(scope.numPages);
128187
}
129-
};
188+
});
130189
}
131190
};
132191
}]);

src/pagination/test/pager.spec.js

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
describe('pager directive with default configuration', function () {
2+
var $rootScope, element;
3+
beforeEach(module('ui.bootstrap.pagination'));
4+
beforeEach(module('template/pagination/pager.html'));
5+
beforeEach(inject(function(_$compile_, _$rootScope_) {
6+
$compile = _$compile_;
7+
$rootScope = _$rootScope_;
8+
$rootScope.numPages = 5;
9+
$rootScope.currentPage = 3;
10+
element = $compile('<pager num-pages="numPages" current-page="currentPage"></pager>')($rootScope);
11+
$rootScope.$digest();
12+
}));
13+
14+
it('has a "pager" css class', function() {
15+
expect(element.hasClass('pager')).toBe(true);
16+
});
17+
18+
it('contains 2 li elements', function() {
19+
expect(element.find('li').length).toBe(2);
20+
expect(element.find('li').eq(0).text()).toBe('« Previous');
21+
expect(element.find('li').eq(-1).text()).toBe('Next »');
22+
});
23+
24+
it('aligns previous & next page', function() {
25+
expect(element.find('li').eq(0).hasClass('previous')).toBe(true);
26+
expect(element.find('li').eq(0).hasClass('next')).toBe(false);
27+
28+
expect(element.find('li').eq(-1).hasClass('previous')).toBe(false);
29+
expect(element.find('li').eq(-1).hasClass('next')).toBe(true);
30+
});
31+
32+
it('disables the "previous" link if current-page is 1', function() {
33+
$rootScope.currentPage = 1;
34+
$rootScope.$digest();
35+
expect(element.find('li').eq(0).hasClass('disabled')).toBe(true);
36+
});
37+
38+
it('disables the "next" link if current-page is num-pages', function() {
39+
$rootScope.currentPage = 5;
40+
$rootScope.$digest();
41+
expect(element.find('li').eq(-1).hasClass('disabled')).toBe(true);
42+
});
43+
44+
it('changes currentPage if the "previous" link is clicked', function() {
45+
var previous = element.find('li').eq(0).find('a').eq(0);
46+
previous.click();
47+
$rootScope.$digest();
48+
expect($rootScope.currentPage).toBe(2);
49+
});
50+
51+
it('changes currentPage if the "next" link is clicked', function() {
52+
var next = element.find('li').eq(-1).find('a').eq(0);
53+
next.click();
54+
$rootScope.$digest();
55+
expect($rootScope.currentPage).toBe(4);
56+
});
57+
58+
it('does not change the current page on "previous" click if already at first page', function() {
59+
var previous = element.find('li').eq(0).find('a').eq(0);
60+
$rootScope.currentPage = 1;
61+
$rootScope.$digest();
62+
previous.click();
63+
$rootScope.$digest();
64+
expect($rootScope.currentPage).toBe(1);
65+
});
66+
67+
it('does not change the current page on "next" click if already at last page', function() {
68+
var next = element.find('li').eq(-1).find('a').eq(0);
69+
$rootScope.currentPage = 5;
70+
$rootScope.$digest();
71+
next.click();
72+
$rootScope.$digest();
73+
expect($rootScope.currentPage).toBe(5);
74+
});
75+
76+
it('executes the onSelectPage expression when the current page changes', function() {
77+
$rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
78+
element = $compile('<pager num-pages="numPages" current-page="currentPage" on-select-page="selectPageHandler(page)"></pager>')($rootScope);
79+
$rootScope.$digest();
80+
var next = element.find('li').eq(-1).find('a').eq(0);
81+
next.click();
82+
$rootScope.$digest();
83+
expect($rootScope.selectPageHandler).toHaveBeenCalledWith(4);
84+
});
85+
86+
it('does not changes the number of items when numPages changes', function() {
87+
$rootScope.numPages = 8;
88+
$rootScope.$digest();
89+
expect(element.find('li').length).toBe(2);
90+
expect(element.find('li').eq(0).text()).toBe('« Previous');
91+
expect(element.find('li').eq(-1).text()).toBe('Next »');
92+
});
93+
94+
it('sets the current page to the last page if the numPages is changed to less than the current page', function() {
95+
$rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
96+
element = $compile('<pager num-pages="numPages" current-page="currentPage" on-select-page="selectPageHandler(page)"></pager>')($rootScope);
97+
$rootScope.$digest();
98+
$rootScope.numPages = 2;
99+
$rootScope.$digest();
100+
expect(element.find('li').length).toBe(2);
101+
expect($rootScope.currentPage).toBe(2);
102+
expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2);
103+
});
104+
});
105+
106+
describe('setting pagerConfig', function() {
107+
var $rootScope, element;
108+
var originalConfig = {};
109+
beforeEach(module('ui.bootstrap.pagination'));
110+
beforeEach(module('template/pagination/pager.html'));
111+
beforeEach(inject(function(_$compile_, _$rootScope_, pagerConfig) {
112+
$compile = _$compile_;
113+
$rootScope = _$rootScope_;
114+
$rootScope.numPages = 5;
115+
$rootScope.currentPage = 3;
116+
angular.extend(originalConfig, pagerConfig);
117+
pagerConfig.previousText = 'PR';
118+
pagerConfig.nextText = 'NE';
119+
pagerConfig.align = false;
120+
element = $compile('<pager num-pages="numPages" current-page="currentPage"></pager>')($rootScope);
121+
$rootScope.$digest();
122+
}));
123+
afterEach(inject(function(pagerConfig) {
124+
// return it to the original state
125+
angular.extend(pagerConfig, originalConfig);
126+
}));
127+
128+
it('contains 2 li elements', function() {
129+
expect(element.find('li').length).toBe(2);
130+
});
131+
132+
it('should change paging text', function () {
133+
expect(element.find('li').eq(0).text()).toBe('PR');
134+
expect(element.find('li').eq(-1).text()).toBe('NE');
135+
});
136+
137+
it('should not align previous & next page link', function () {
138+
expect(element.find('li').eq(0).hasClass('previous')).toBe(false);
139+
expect(element.find('li').eq(-1).hasClass('next')).toBe(false);
140+
});
141+
142+
});
143+
144+
describe('pagination bypass configuration from attributes', function () {
145+
var $rootScope, element;
146+
beforeEach(module('ui.bootstrap.pagination'));
147+
beforeEach(module('template/pagination/pager.html'));
148+
beforeEach(inject(function(_$compile_, _$rootScope_) {
149+
$compile = _$compile_;
150+
$rootScope = _$rootScope_;
151+
$rootScope.numPages = 5;
152+
$rootScope.currentPage = 3;
153+
element = $compile('<pager align="false" previous-text="\'<\'" next-text="\'>\'" num-pages="numPages" current-page="currentPage"></pager>')($rootScope);
154+
$rootScope.$digest();
155+
}));
156+
157+
it('contains 2 li elements', function() {
158+
expect(element.find('li').length).toBe(2);
159+
});
160+
161+
it('should change paging text from attributes', function () {
162+
expect(element.find('li').eq(0).text()).toBe('<');
163+
expect(element.find('li').eq(-1).text()).toBe('>');
164+
});
165+
166+
it('should not align previous & next page link', function () {
167+
expect(element.find('li').eq(0).hasClass('previous')).toBe(false);
168+
expect(element.find('li').eq(-1).hasClass('next')).toBe(false);
169+
});
170+
171+
});

template/pagination/pager.html

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div class="pager">
2+
<ul>
3+
<li ng-repeat="page in pages" ng-class="{disabled: page.disabled, previous: page.previous, next: page.next}"><a ng-click="selectPage(page.number)">{{page.text}}</a></li>
4+
</ul>
5+
</div>

0 commit comments

Comments
 (0)