├── examples
├── label.html
├── simple.html
├── simple.js
└── label.js
├── tests
├── runner.html
└── index.spec.js
├── index.js
├── src
├── index.js
└── Pager.jsx
├── HISTORY.md
├── .editorconfig
├── .gitignore
├── .npmignore
├── .travis.yml
├── package.json
├── assets
└── bootstrap.less
└── README.md
/examples/label.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/simple.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/runner.html:
--------------------------------------------------------------------------------
1 | stub
2 |
3 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('./src/');
4 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('./Pager');
4 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | # History
2 | ----
3 |
4 | ## 2.2.0 / 2015-06-01
5 |
6 | `new` [https://github.com/react-component/pager/pull/3](https://github.com/react-component/pager/pull/3) add previousLabel and nextlabel
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*.{js,css}]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | indent_style = space
9 | indent_size = 2
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.log
3 | .idea/
4 | .ipr
5 | .iws
6 | *~
7 | ~*
8 | *.diff
9 | *.patch
10 | *.bak
11 | .DS_Store
12 | Thumbs.db
13 | .project
14 | .*proj
15 | .svn/
16 | *.swp
17 | *.swo
18 | *.pyc
19 | *.pyo
20 | .build
21 | node_modules
22 | .cache
23 | dist
24 | assets/**/*.css
25 | build
26 | lib
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | build/
2 | *.cfg
3 | nohup.out
4 | *.iml
5 | .idea/
6 | .ipr
7 | .iws
8 | *~
9 | ~*
10 | *.diff
11 | *.log
12 | *.patch
13 | *.bak
14 | .DS_Store
15 | Thumbs.db
16 | .project
17 | .*proj
18 | .svn/
19 | *.swp
20 | out/
21 | .build
22 | node_modules
23 | .cache
24 | examples
25 | tests
26 | src
27 | /index.js
28 | .*
29 | assets/**/*.less
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | notifications:
4 | email:
5 | - yiminghe@gmail.com
6 |
7 | node_js:
8 | - 0.12
9 |
10 | before_install:
11 | - |
12 | if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/'
13 | then
14 | echo "Only docs were updated, stopping build process."
15 | exit
16 | fi
17 | npm install mocha-phantomjs -g
18 | phantomjs --version
19 |
20 | script:
21 | - |
22 | if [ "$TEST_TYPE" = test ]; then
23 | npm test
24 | else
25 | npm run $TEST_TYPE
26 | fi
27 |
28 | env:
29 | matrix:
30 | - TEST_TYPE=lint
31 | - TEST_TYPE=browser-test
32 | - TEST_TYPE=browser-test-cover
33 | - TEST_TYPE=saucelabs
--------------------------------------------------------------------------------
/examples/simple.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var Pager = require('rc-pager');
5 |
6 | require('rc-pager/assets/bootstrap.css');
7 |
8 | class MyControl extends React.Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | current: 0
13 | };
14 | }
15 |
16 | handleSkip(page) {
17 | this.setState({
18 | current: page
19 | });
20 |
21 | if (this.props.onSkipTo) {
22 | this.props.onSkipTo(page);
23 | }
24 | }
25 |
26 | render() {
27 | return (
28 |
31 | );
32 | }
33 | }
34 |
35 | React.render(
36 |
37 |
simple pager
38 |
39 | ,
40 | document.getElementById('__react-content')
41 | );
42 |
--------------------------------------------------------------------------------
/examples/label.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var Pager = require('rc-pager');
5 |
6 | require('rc-pager/assets/bootstrap.css');
7 |
8 | class MyControl extends React.Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | current: 0
13 | };
14 | }
15 |
16 | handleSkip(page) {
17 | this.setState({
18 | current: page
19 | });
20 |
21 | if (this.props.onSkipTo) {
22 | this.props.onSkipTo(page);
23 | }
24 | }
25 |
26 | render() {
27 | return (
28 |
35 | );
36 | }
37 | }
38 |
39 | React.render(
40 |
41 |
simple pager
42 |
43 | ,
44 | document.getElementById('__react-content')
45 | );
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rc-pager",
3 | "version": "2.2.0",
4 | "description": "pager ui component for react",
5 | "keywords": [
6 | "react",
7 | "react-pager"
8 | ],
9 | "main": "./lib/index",
10 | "homepage": "http://github.com/react-component/pager",
11 | "maintainers": [
12 | "yiminghe@gmail.com",
13 | "dxq613@gmail.com"
14 | ],
15 | "repository": {
16 | "type": "git",
17 | "url": "git@github.com:react-component/pager.git"
18 | },
19 | "bugs": {
20 | "url": "http://github.com/react-component/pager/issues"
21 | },
22 | "licenses": "MIT",
23 | "config": {
24 | "port": 8000
25 | },
26 | "scripts": {
27 | "build": "rc-tools run build",
28 | "precommit": "rc-tools run precommit",
29 | "less": "rc-tools run less",
30 | "gh-pages": "rc-tools run gh-pages",
31 | "history": "rc-tools run history",
32 | "start": "node --harmony node_modules/.bin/rc-server",
33 | "publish": "rc-tools run tag",
34 | "lint": "rc-tools run lint",
35 | "saucelabs": "node --harmony node_modules/.bin/rc-tools run saucelabs",
36 | "browser-test": "node --harmony node_modules/.bin/rc-tools run browser-test",
37 | "browser-test-cover": "node --harmony node_modules/.bin/rc-tools run browser-test-cover"
38 | },
39 | "devDependencies": {
40 | "expect.js": "~0.3.1",
41 | "jquery": "^1.11.2",
42 | "precommit-hook": "^1.0.7",
43 | "rc-server": "3.x",
44 | "rc-tools": "3.x",
45 | "react": "~0.13.0",
46 | "sinon": "1.x"
47 | },
48 | "precommit": [
49 | "precommit"
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------
/assets/bootstrap.less:
--------------------------------------------------------------------------------
1 | .rc-pager {
2 | display: inline-block;
3 | padding-left: 0;
4 | margin: 20px 0;
5 | border-radius: 4px;
6 | }
7 | .rc-pager > li {
8 | display: inline;
9 | }
10 | .rc-pager > li > a,
11 | .rc-pager > li > span {
12 | position: relative;
13 | float: left;
14 | padding: 6px 12px;
15 | margin-left: -1px;
16 | line-height: 1.42857143;
17 | color: #337ab7;
18 | text-decoration: none;
19 | background-color: #fff;
20 | border: 1px solid #ddd;
21 | }
22 | .rc-pager > li:first-child > a,
23 | .rc-pager > li:first-child > span {
24 | margin-left: 0;
25 | border-top-left-radius: 4px;
26 | border-bottom-left-radius: 4px;
27 | }
28 | .rc-pager > li:last-child > a,
29 | .rc-pager > li:last-child > span {
30 | border-top-right-radius: 4px;
31 | border-bottom-right-radius: 4px;
32 | }
33 | .rc-pager > li > a:hover,
34 | .rc-pager > li > span:hover,
35 | .rc-pager > li > a:focus,
36 | .rc-pager > li > span:focus {
37 | color: #23527c;
38 | background-color: #eee;
39 | border-color: #ddd;
40 | }
41 | .rc-pager > .rc-pager-item-active > a,
42 | .rc-pager > .rc-pager-item-active > span,
43 | .rc-pager > .rc-pager-item-active > a:hover,
44 | .rc-pager > .rc-pager-item-active > span:hover,
45 | .rc-pager > .rc-pager-item-active > a:focus,
46 | .rc-pager > .rc-pager-item-active > span:focus {
47 | z-index: 2;
48 | color: #fff;
49 | cursor: default;
50 | background-color: #337ab7;
51 | border-color: #337ab7;
52 | }
53 | .rc-pager > .rc-pager-item-disabled > span,
54 | .rc-pager > .rc-pager-item-disabled > span:hover,
55 | .rc-pager > .rc-pager-item-disabled > span:focus,
56 | .rc-pager > .rc-pager-item-disabled > a,
57 | .rc-pager > .rc-pager-item-disabled > a:hover,
58 | .rc-pager > .rc-pager-item-disabled > a:focus {
59 | color: #777;
60 | cursor: not-allowed;
61 | background-color: #fff;
62 | border-color: #ddd;
63 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rc-pager
2 |
3 | react pager component
4 |
5 | [![NPM version][npm-image]][npm-url]
6 | [![build status][travis-image]][travis-url]
7 | [![Test coverage][coveralls-image]][coveralls-url]
8 | [![gemnasium deps][gemnasium-image]][gemnasium-url]
9 | [![node version][node-image]][node-url]
10 | [![npm download][download-image]][download-url]
11 |
12 | [npm-image]: http://img.shields.io/npm/v/rc-pager.svg?style=flat-square
13 | [npm-url]: http://npmjs.org/package/rc-pager
14 | [travis-image]: https://img.shields.io/travis/react-component/pager.svg?style=flat-square
15 | [travis-url]: https://travis-ci.org/react-component/pager
16 | [coveralls-image]: https://img.shields.io/coveralls/react-component/pager.svg?style=flat-square
17 | [coveralls-url]: https://coveralls.io/r/react-component/pager?branch=master
18 | [gemnasium-image]: http://img.shields.io/gemnasium/react-component/pager.svg?style=flat-square
19 | [gemnasium-url]: https://gemnasium.com/react-component/pager
20 | [node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square
21 | [node-url]: http://nodejs.org/download/
22 | [download-image]: https://img.shields.io/npm/dm/rc-pager.svg?style=flat-square
23 | [download-url]: https://npmjs.org/package/rc-pager
24 |
25 | ## install
26 |
27 | [](https://npmjs.org/package/rc-pager)
28 |
29 | ## Usage
30 |
31 | ```js
32 | var Pager = require('rc-pager');
33 | React.renderComponent(
34 | ,
35 | document.getElementById('p1')
36 | );
37 | ```
38 |
39 | ## Development
40 |
41 | ```
42 | npm install
43 | npm start
44 | ```
45 |
46 | ## Example
47 |
48 | http://localhost:8000/examples/
49 |
50 | online example:
51 |
52 | http://react-component.github.io/pager/build/examples/index.html
53 |
54 | ## API
55 |
56 | #### total `Number`
57 |
58 | * total page
59 |
60 | #### current `Number`
61 |
62 | * current page
63 |
64 | #### previousLabel `String|Element`
65 |
66 | * previous page label, also can be a React Component
67 |
68 | #### nextLabel `String|Element`
69 |
70 | * next page label, also can be a React Component
71 |
72 | #### onSkipTo(page) `Function`
73 |
74 | * The callback when the page skip
75 |
76 | ## Test Case
77 |
78 | http://localhost:8000/tests/runner.html?coverage
79 |
80 | ## Coverage
81 |
82 | http://localhost:8000/node_modules/rc-server/node_modules/node-jscover/lib/front-end/jscoverage.html?w=http://localhost:8000/tests/runner.html?coverage
83 |
84 | ## License
85 |
86 | rc-pager is released under the MIT license.
87 |
--------------------------------------------------------------------------------
/src/Pager.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 |
5 | class PagerItem extends React.Component {
6 | handleClick(ev) {
7 | ev.preventDefault();
8 | if (!this.props.active && !this.props.disabled) {
9 | this.props.skipTo(this.props.page);
10 | }
11 | }
12 |
13 | render() {
14 | var status = this.props.active ? 'rc-pager-item-active' : '';
15 | if (this.props.disabled) {
16 | status += ' rc-pager-item-disabled';
17 | }
18 | return (
19 | {this.props.text}
20 | );
21 | }
22 | }
23 |
24 | /**
25 | * @private
26 | * 命令子项
27 | */
28 | class CmdItem extends React.Component {
29 | handleClick(ev) {
30 | ev.preventDefault();
31 | if (!this.props.disabled) {
32 | this.props.skipTo(this.props.page);
33 | }
34 | }
35 |
36 | render() {
37 | var disabled = this.props.disabled ? 'rc-pager-item-disabled' : '';
38 | return (
39 |
40 | {this.props.text}
41 |
42 | );
43 | }
44 | }
45 |
46 | //分页栏
47 | class Pager extends React.Component {
48 | constructor(props) {
49 | super(props);
50 | this.skipTo = this.skipTo.bind(this);
51 | }
52 |
53 | //获取首页按钮
54 | _getFirstItem() {
55 | var self = this,
56 | props = self.props,
57 | current = props.current,
58 | disabled = current === 0,
59 | label = props.previousLabel || '«';
60 |
61 | return ;
62 | }
63 |
64 | //获取最后一页按钮
65 | _getLastItem() {
66 | var self = this,
67 | total = self.props.total,
68 | current = self.props.current,
69 | disabled = current === total - 1,
70 | label = self.props.nextLabel || '»';
71 |
72 | return ;
73 | }
74 |
75 | //获取所有数字按钮
76 | _getItems() {
77 | var self = this,
78 | total = self.props.total,
79 | current = self.props.current,
80 | rst = [],
81 | from = 0,
82 | active,
83 | skip = 2,
84 | to = total - 1;
85 |
86 | if (current > skip) {
87 | from = current - skip;
88 | }
89 | if (total - current > skip) {
90 | to = current + skip;
91 | }
92 | if (from !== 0) {
93 | rst.push();
94 | if (from > 1) {
95 | rst.push();
96 | }
97 | }
98 |
99 | for (var i = from; i <= to; i++) {
100 | active = current === i;
101 | rst.push();
102 | }
103 |
104 | if (to < total - 1) {
105 | active = current === total - 1;
106 | if (to < total - 2) {
107 | rst.push();
108 | }
109 | rst.push();
110 | }
111 | return rst;
112 | }
113 |
114 | /**
115 | * 跳转到对应的节点
116 | * @param {Number} page 页码
117 | */
118 | skipTo(page) {
119 | var handler = this.props.onSkipTo;
120 | if (handler) {
121 | handler(page);
122 | }
123 | }
124 |
125 | render() {
126 | var self = this,
127 | first = self._getFirstItem(),
128 | last = self._getLastItem(),
129 | items = self._getItems();
130 |
131 | var className = 'rc-pager';
132 | if (this.props.className) {
133 | className += ' ' + this.props.className;
134 | }
135 |
136 | return (
137 |
138 | {first}
139 | {items}
140 | {last}
141 |
142 | );
143 | }
144 | }
145 |
146 | module.exports = Pager;
147 |
--------------------------------------------------------------------------------
/tests/index.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var expect = require('expect.js');
4 | var Pager = require('../index');
5 | var React = require('react/addons');
6 | var TestUtils = React.addons.TestUtils;
7 | var Simulate = TestUtils.Simulate;
8 | var sinon = require('sinon');
9 | var $ = require('jquery');
10 |
11 | require('../assets/bootstrap.css');
12 |
13 | $('').appendTo('body');
14 | $('').appendTo('body');
15 | $('').appendTo('body');
16 | $('').appendTo('body');
17 | $('').appendTo('body');
18 | $('').appendTo('body');
19 | $('').appendTo('body');
20 | $('').appendTo('body');
21 |
22 | var total = 10;
23 | describe('rc-pager', function () {
24 | var current = 3;
25 |
26 | var pager = React.render(
27 | ,
28 | document.getElementById('t1')
29 | );
30 |
31 | var node = $('#t1');
32 |
33 | it('create', function () {
34 | expect(node.children().length).not.to.be(0);
35 | });
36 |
37 | it('previousLabel and nextLabel support', function() {
38 | expect(node.find('li:first-child').text()).to.be('prev');
39 | expect(node.find('li:last-child').text()).to.be('next');
40 | });
41 |
42 | it('page struct', function () {
43 | expect(node.find('.rc-pager').length).to.be(1);
44 | expect(node.find('li').length).not.to.be(0);
45 | });
46 |
47 | it('page current', function () {
48 | expect(pager.props.current).to.be(current);
49 | expect(pager.props.total).to.be(total);
50 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
51 | });
52 |
53 | describe('rc-pager chang init', function () {
54 | it('init current last', function () {
55 | var current = 9,
56 | node = $('#t2');
57 | React.render(
58 | ,
59 | document.getElementById('t2')
60 | );
61 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
62 | expect(node.find('li').last().hasClass('rc-pager-item-disabled')).to.be(true);
63 | });
64 |
65 | it('current first', function () {
66 | var current = 0,
67 | node = $('#t3');
68 | React.render(
69 | ,
70 | document.getElementById('t3')
71 | );
72 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
73 | expect(node.find('li').first().hasClass('rc-pager-item-disabled')).to.be(true);
74 | });
75 |
76 | it('skip to middle', function () {
77 | var current = 5,
78 | node = $('#t4');
79 | React.render(
80 | ,
81 | document.getElementById('t4')
82 | );
83 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
84 | expect(node.find('li').first().hasClass('rc-pager-item-disabled')).to.be(false);
85 | expect(node.find('li').last().hasClass('rc-pager-item-disabled')).to.be(false);
86 | });
87 |
88 | it('skip to second', function () {
89 | var current = 1,
90 | node = $('#t6');
91 | React.render(
92 | ,
93 | document.getElementById('t6')
94 | );
95 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
96 | expect(node.find('li').first().hasClass('rc-pager-item-disabled')).to.be(false);
97 | expect(node.find('li').last().hasClass('rc-pager-item-disabled')).to.be(false);
98 | });
99 |
100 | it('skip to last - 1', function () {
101 | var current = 7,
102 | node = $('#t7');
103 | React.render(
104 | ,
105 | document.getElementById('t7')
106 | );
107 | expect(node.find('.rc-pager-item-active').text()).to.be((current + 1).toString());
108 | expect(node.find('li').first().hasClass('rc-pager-item-disabled')).to.be(false);
109 | expect(node.find('li').last().hasClass('rc-pager-item-disabled')).to.be(false);
110 | });
111 | });
112 |
113 | describe('test event', function () {
114 | var node = $('#t5');
115 | var callback = sinon.spy();
116 | React.render(
117 | ,
118 | document.getElementById('t5')
119 | );
120 |
121 | it('test event', function () {
122 | var last = node.find('li').last()[0];
123 | Simulate.click(last);
124 | expect(callback.called).to.be(true);
125 | });
126 |
127 | it('test first ', function () {
128 | callback.called = false;
129 | var first = node.find('li').first()[0];
130 | Simulate.click(first);
131 | expect(callback.called).to.be(false);
132 | var second = node.find('li')[1];
133 | Simulate.click(first);
134 | expect(callback.called).to.be(false);
135 | var ellipsis = node.find('li')[4];
136 | Simulate.click(ellipsis);
137 | expect(callback.called).to.be(false);
138 | });
139 | })
140 | });
141 |
--------------------------------------------------------------------------------