react-ui-component
Version:
some component build with ReactJs
203 lines (180 loc) • 6.08 kB
JavaScript
const React = require('react')
const Component = React.Component
const PropTypes = require('prop-types')
const ReactDOM = require('react-dom')
const klassName = require('./util/className')
const ENTER_KEYCODE = require('./util/constants').ENTER_KEYCODE
class Pagination extends Component {
constructor(props) {
super(props);
this.onPageChange = this.onPageChange.bind(this)
this.handlePageJump = this.handlePageJump.bind(this)
const {current} = props;
this.state = {
current
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.current != this.props.current) {
this.setState({
current: nextProps.current || 1,
});
}
}
onPageChange(page){
const {total, onChange} = this.props;
if (page > total) return;
this.setState({
current: page
});
if (onChange) onChange(page);
}
formatFirstNode(begin){
const {showRange, showNav, prev, start} = this.props;
const {current} = this.state;
let firstNode = null;
if (showRange && begin != 1) {
firstNode = <li key='first-page' onClick={() => this.onPageChange(1)}
className={current === 1 ? '_active _range _item': '_range _item'}>
{start ? start : <span>1 </span>}
<span> ...</span>
</li>
} else if (showNav && begin != 1) {
firstNode = <li className="_item _nav _prev" key='previous-page' onClick={() => this.onPageChange(current - 1)}>
{ prev ? prev : <span>prev</span> }
</li>
}
return firstNode;
}
formatLastNode(last){
const {showRange, showNav, next, end, isEnd, total} = this.props;
const {current} = this.state;
let lastNode = null;
if (showRange && last !== total) {
lastNode = <li key={`last-page`} onClick={() => this.onPageChange(total)}
className={current === total ? '_active _range _item': '_range _item'}>
<span>... </span>
{end ? end : <span>{total}</span>}
</li>
} else if(showNav && !isEnd && last !== total){
lastNode = <li className="_item _nav _prev" key="next-page" onClick={() => this.onPageChange(current + 1)}>
{next ? next : <span>next</span>}
</li>
}
return lastNode;
}
formatStartAndEnd(){
let {range, total} = this.props;
const { current } = this.state;
let start = 1,
end = 1,
left_half = Math.ceil(range / 2);
// current large than half
if (current > left_half) start = current - left_half;
// calc end
end = start + range;
if (total - start <= range) {
start = total - range;
end = total;
}
if (start < 1) {
start = 1
}
if (range >= total) {
range = total - 1
}
if (end > total) {
end = total
}
return {
start, end
}
}
formatRange(start, end){
let {isEnd} = this.props;
const {current} = this.state;
let nodes = [];
for (let i = start; i <= end; i++) {
if (isEnd && current === i - 1) break;
nodes.push(<li key={`page-link-${i}`} onClick={() => this.onPageChange(i)}
className={current === i ? '_active _item': '_item'}>
<span>{i}</span>
</li>);
}
return nodes;
}
handlePageJump(e){
let {total} = this.props
// blur || keyDown
if (e.keyCode === undefined || e.keyCode === ENTER_KEYCODE) {
let value = parseInt(e.target.value) || 1
if (value < 1) {
value = 1
}
if (value > total) {
value = total
}
this.setState({
current: value
});
let {onChange} = this.props
if (onChange) {
onChange(value)
}
if (value != e.target.value) {
let jumpInput = ReactDOM.findDOMNode(this.jumpInput)
jumpInput.value = value
}
}
}
formatJump(){
const {showJump} = this.props
const {current} = this.state
if (showJump) {
return (
<li key={'jump-page'} className="_item _jump">
<span>Go </span>
<input type="number"
ref={ ref => { this.jumpInput = ref } }
defaultValue={current + 1}
onBlur={this.handlePageJump}
onKeyDown={this.handlePageJump}/>
</li>
)
}
}
render() {
let {start, end} = this.formatStartAndEnd();
let {className} = this.props;
className = klassName(className, 'pagination')
return (
<ul className={className}>
{this.formatFirstNode(start)}
{this.formatRange(start, end)}
{this.formatLastNode(end)}
{this.formatJump()}
</ul>
);
}
}
Pagination.propTypes = {
onChange: PropTypes.func,
total: PropTypes.number,
current: PropTypes.number,
showRange: PropTypes.bool,
showNav: PropTypes.bool,
isEnd: PropTypes.bool,
range: PropTypes.number,
start: PropTypes.element,
end: PropTypes.element,
prev: PropTypes.element,
next: PropTypes.element,
showJump: PropTypes.bool,
}
Pagination.defaultProps = {
current: 1,
range: 7,
total: 30,
showJump: false,
}
module.exports = Pagination;