Home Reference Source

application/components/common/sliding-paginator.js

import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router';
import Request from './../../util/request';
import URI from 'urijs';

/**
 * Pagination component. Currently, updates the URL for each
 * page change. Use the onPaginate parameter to watch for changes.
 * Expects pagination property to be API standard.
 */
class SlidingPaginator extends React.Component {

    constructor(props) {
        super(props);

        this.onPaginate = this.onPaginate.bind(this);
    }

    onPaginate(...params) {
        if (this.props.onPaginate) {
            this.props.onPaginate(...params);
        }
    }

    render() {
        if (!this.props.totalItems) {
            return (
                <ul className="pagination"></ul>
            );
        }

        let pages = [];
        let url = Request.getPath();

        const currentPage = parseInt(this.props.currentPage);
        const perPage = parseInt(this.props.perPage);
        const totalItems = parseInt(this.props.totalItems);

        const totalPages = Math.ceil(totalItems / perPage);

        let previousClass = 'waves-effect';
        if (currentPage == 1) {
            previousClass = 'disabled';
        }
        let nextClass = '';
        if (currentPage >= totalPages) {
            nextClass = 'disabled';
        }

        const nextPage = (currentPage < totalPages) ? currentPage + 1 : totalPages;
        const prevPage = (currentPage > 1) ? currentPage - 1 : 1;

        const prevQuery = Request.setQuery({'page': prevPage});
        const nextQuery = Request.setQuery({'page': nextPage});

        const previous = (
            <li className={previousClass}>
                <Link to={url + '?' + prevQuery} onClick={this.onPaginate.bind(this, prevPage)}><i className='fa fa-chevron-left'></i></Link>
            </li>
        );
        const next = (
            <li className={nextClass}>
                <Link to={url + '?' + nextQuery} onClick={this.onPaginate.bind(this, nextPage)}><i className='fa fa-chevron-right'></i></Link>
            </li>
        );

        if (totalPages <= 8) {
            for (let i = 0; i < totalPages; i++) {
                const newQuery = Request.setQuery({'page': (i+1)});
                pages.push((
                    <li key={(i+1)} className={((i+1) === currentPage) ? 'active' : 'waves-effect'}>
                        <Link to={url + '?' + newQuery} onClick={this.onPaginate.bind(this, (i+1))}>{(i+1)}</Link>
                    </li>
                ));
            }
        } else {
            let start = 1;
            if (currentPage > 6) {
                start = currentPage - 5;
            }
            let max = start+10;
            if (totalPages <= 10 || max >= totalPages) {
                max = totalPages + 1;
            }
            for (let i = start; i < max; i++) {
                const newQuery = Request.setQuery({'page': i});
                pages.push((
                    <li key={i} className={(i === currentPage) ? 'active' : 'waves-effect'}>
                        <Link to={url + '?' + newQuery} onClick={this.onPaginate.bind(this, i)}>{i}</Link>
                    </li>
                ));
            }
        }

        return (
            <ul className="pagination">
                {previous}
                {pages}
                {next}
            </ul>
        );

    }
}

SlidingPaginator.propTypes = {
    currentPage: PropTypes.number,
    perPage: PropTypes.number,
    totalItems: PropTypes.number,
    onPaginate: PropTypes.func
};

export default SlidingPaginator;