hjyssg / ShiguReader

硬核宅宅资源管理器. Ultimate Manga Resource Manager
MIT License
400 stars 45 forks source link

pagination #57

Closed hjyssg closed 4 years ago

hjyssg commented 4 years ago
class AjiPagination extends Component {
    constructor (props) {
      super()
      this.state = {
        textValue: props.currentPage
      }
    }

    componentWillReceiveProps (nextProps) {
      if (this.props.currentPage !== nextProps.currentPage) {
        this.setState({ textValue: nextProps.currentPage })
      }
    }

    onChange = (e) => {
      const {onChange} = this.props;
      const value = typeof e === "number"? e : parseInt(e.target.textContent.trim());
      onChange && onChange(value);
    }

    prev = () => {
      const {onChange, currentPage} = this.props;
      onChange && onChange(Math.max(currentPage - 1, 1));
    }

    next = () => {
      const {onChange, currentPage} = this.props;
      onChange && onChange(Math.min(currentPage + 1, this.getTotalPage()));
    }

    getTotalPage(){
      const {
        itemPerPage,
        totalItemNum,
      } = this.props
      return Math.ceil(totalItemNum/itemPerPage);
    }

    getSafePage (page) {
      if (Number.isNaN(page)) {
        page = this.props.currentPage
      }
      return Math.min(Math.max(page, 1), this.getTotalPage());
    }

    render(){
      const {
        currentPage,
        itemPerPage,
        totalItemNum,
        onChange,
        className,
      } = this.props

      const {textValue} = this.state;

      const BUFFER_SIZE = 3; //the items will 1 + BUFFER_SIZE*2
      const totalPage = this.getTotalPage();

      if(totalPage <= 1){
        return null;
      }

      const prevButton = (<div className="pagination-item prev" onClick={this.prev}> prev </div>)
      const nextButton = (<div className="pagination-item next" onClick={this.next}> next </div>)

      let right = Math.max(currentPage - BUFFER_SIZE, 1);
      let left = Math.min(currentPage + BUFFER_SIZE, totalPage);

      if(currentPage - right < BUFFER_SIZE){
        const toLeft = BUFFER_SIZE - (currentPage - right);
        left = Math.min(currentPage + BUFFER_SIZE + toLeft, totalPage);
      }

      if(left - currentPage < BUFFER_SIZE){
        const toRight = BUFFER_SIZE - (left - currentPage);
        right = Math.max(currentPage - BUFFER_SIZE - toRight, 1);
      }

      const one = (<li className="pagination-item" key={1} onClick={this.onChange}> 1 </li>);
      const ellipsis1 =  (<li className="pagination-item ellipsis" key="ellipsis-1"> ... </li>);
      const ellipsis2 =  (<li className="pagination-item ellipsis" key="ellipsis-2"> ... </li>);
      const end = (<li className="pagination-item" key={totalPage} onClick={this.onChange} > {totalPage} </li>);

      let contentList = [];
      contentList.push(prevButton);
      if(right > 1){
        contentList.push(one);
        if(right > 2){
          contentList.push(ellipsis1);
        }
      }

      for(let ii = right; ii <= left; ii++){
        contentList.push(<li className="pagination-item" key={ii} onClick={this.onChange}> {ii} </li>);
      }

      if(left < totalPage){
        if(left < totalPage - 1){
          contentList.push(ellipsis2);
        }
        contentList.push(end);
      }

      contentList.push(nextButton);

      const pageInput = (
        <div className="-pageJump">
          <input
            type='text'
            value={textValue||currentPage}
            onKeyPress={e => {
              if (e.which === 13 || e.keyCode === 13) {
                //enter key
                this.onChange(parseInt(textValue));
              }
            }}

            onChange={e => {
              const val = e.target.value
              this.setState({ textValue: val })
            }}
          />
          <div>{`/${totalPage}`}</div>
        </div>)

      return (<ul className="pagination">
                {contentList}
                {pageInput}
              </ul>);
    }
  }