labo-components
Version:
177 lines (155 loc) • 3.72 kB
JSX
import React from 'react'
import IDUtil from '../../../util/IDUtil';
import PropTypes from 'prop-types';
/**
* Pagination element that shows page numbers around the current page
* and Previous and Next buttons
*
* This component was forked from DIVE+
*/
class Pagination extends React.PureComponent {
/**
* Pagination onClick handler
*
* @param {int} page Page number
*/
onClick(page) {
this.props.onClick(page);
}
/**
* Get pagination boundaries
*
* @param {int} currentPage Current page
* @param {int} pageCount Page count or total number of pages
* @param {int} maxOffset Maximum offset
* @return {object} Object containing start and end
*/
getBoundaries(currentPage, pageCount, maxOffset) {
let start = currentPage - maxOffset;
let end = currentPage + maxOffset;
// calculate boundaries
if (start < 1) {
end += 1 - start;
start = 0;
}
if (end > pageCount - 1) {
start += pageCount - 1 - end;
end = pageCount - 1;
if (start < 1) {
start = 0;
}
}
// prevent dots for a single number
if (start === 2) {
start--;
end--;
}
// compensate for missing dots
if (start <= 1) {
end++;
}
// prevent dots for a single number
if (end === pageCount - 3) {
end++;
start++;
}
// compensate for missing dots
if (end >= pageCount - 2) {
start -= end - (pageCount - maxOffset + (maxOffset - 3));
}
return { start, end };
}
/**
* Get pagination buttons, prev, pages, next
*
* @return {array} Array of pagination buttons (Elements)
*/
getPaginationButtons() {
// result
const result = [];
const boundaries = this.getBoundaries(
this.props.currentPage,
this.props.pageCount,
this.props.maxOffset
);
let prevVisible = false;
// Previous
result.push(
<li
className="prev"
key="prev"
onClick={
this.props.currentPage > 0
? this.onClick.bind(this, this.props.currentPage - 1)
: () => {}
}
>
<
</li>
);
// Numbers
for (let i = 0; i < this.props.pageCount; i++) {
if (
i === 0 ||
i === this.props.pageCount - 1 ||
(i >= boundaries.start && i <= boundaries.end)
) {
prevVisible = true;
result.push(
<li
key={i}
className={this.props.currentPage === i ? 'active' : null}
onClick={this.onClick.bind(this, i)}
>
{i + 1}
</li>
);
} else {
if (prevVisible) {
result.push(<li key={i}>…</li>);
}
prevVisible = false;
}
}
// Next
result.push(
<li
className="next"
key="next"
onClick={
this.props.currentPage < this.props.pageCount - 1
? this.onClick.bind(this, this.props.currentPage + 1)
: () => {}
}
>
>
</li>
);
return result;
}
/**
* React render function
*
* @return {Element}
*/
render() {
return (
<ul className={IDUtil.cssClassName('pagination')}>
{this.getPaginationButtons()}
</ul>
);
}
}
Pagination.propTypes = {
currentPage: PropTypes.number.isRequired,
perPage: PropTypes.number.isRequired,
pageCount: PropTypes.number.isRequired,
maxOffset: PropTypes.number,
onClick: PropTypes.func.isRequired
};
Pagination.defaultProps = {
// when there are many pages, keep this pagination offset
// before/after the current page
maxOffset: 4
};
export default Pagination;